[
  {
    "path": ".codeclimate.yml",
    "content": "version: '2'\nengines:\n  eslint:\n    enabled: false\n  duplication:\n    enabled: true\n    config:\n      languages:\n        - javascript\n    exclude_paths:\n      - test\n      - lib/parsers/FeatureParser.js\n      - lib/localisation/*\nchecks:\n  method-complexity:\n    enabled: false\n  method-lines:\n    enabled: false\n\nratings:\n  paths:\n    - index.js\n    - lib/**\n\nexclude_paths:\n  - bin\n  - dist\n  - examples\n"
  },
  {
    "path": ".eslintignore",
    "content": "coverage/*\nexamples/*\ndist/*\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"extends\": [\"prettier\"],\n  \"plugins\": [\"prettier\"],\n  \"env\": {\n    \"node\": true\n  },\n  \"parserOptions\": {\n    \"ecmaVersion\": 5\n  },\n  \"rules\": {\n    \"no-control-regex\": 0\n  }\n}\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: 'CodeQL'\n\non:\n  push:\n    branches: [master]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [master]\n  schedule:\n    - cron: '39 15 * * 0'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: ['javascript']\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]\n        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n\n      # Initializes the CodeQL tools for scanning.\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v2\n        with:\n          languages: ${{ matrix.language }}\n          # If you wish to specify custom queries, you can do so here or in a config file.\n          # By default, queries listed here will override any specified in a config file.\n          # Prefix the list here with \"+\" to use these queries and those in the config file.\n\n          # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs\n          # queries: security-extended,security-and-quality\n\n      # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n      # If this step fails, then you should remove it and run the build manually (see below)\n      - name: Autobuild\n        uses: github/codeql-action/autobuild@v2\n\n      # ℹ️ Command-line programs to run using the OS shell.\n      # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun\n\n      #   If the Autobuild fails above, remove it and uncomment the following three lines.\n      #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.\n\n      # - run: |\n      #   echo \"Run, Build Application using script\"\n      #   ./location_of_script_within_repo/buildscript.sh\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v2\n"
  },
  {
    "path": ".github/workflows/node-js-ci.yml",
    "content": "name: Node.js CI\n\non: [push]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version: [12.x, 14.x, 16.x, 18.x]\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm ci\n      - run: npx prettier --check .\n      - run: npm run lint\n      - run: npm test\n      - run: npm run karma\n\n  code-climate:\n    needs: build\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          node-version: '14.x'\n      - run: npm ci\n      - run: curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter\n      - run: chmod +x ./cc-test-reporter\n      - run: ./cc-test-reporter before-build\n      - run: npm run coverage\n      - run: ./cc-test-reporter format-coverage -t lcov coverage/lcov.info\n      - run: ./cc-test-reporter upload-coverage\n        env:\n          CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules/\ncoverage/\nnpm-debug.log\n.DS_Store\n*.swp\n*.swo\n*.iml\ncomponents/\nbuild/\n.idea\n.codeclimate\n.nyc_output\n"
  },
  {
    "path": ".husky/.gitignore",
    "content": "_\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpm run lint-staged && npm run test\n\n"
  },
  {
    "path": ".jshintignore",
    "content": "node_modules/*\ndist/*\nexamples/*\ncoverage/*\n"
  },
  {
    "path": ".mocharc.json",
    "content": "{\n  \"timeout\": \"2000\",\n  \"recursive\": true\n}\n"
  },
  {
    "path": ".npmignore",
    "content": ".idea\n.codeclimate\n.nyc_output\nbuild\ncomponents\ncoverage\ndist\nnode_modules\nnpm-debug.log\n.DS_Store\n*.swp\n*.swo\n*.iml\n"
  },
  {
    "path": ".prettierignore",
    "content": "dist\ncoverage\n.nyc_output"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"singleQuote\": true,\n  \"printWidth\": 300\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\n## Unreleased\n\n- Restrict dependabot to direct dependencies\n\n## [2.2.0]\n\n- Add support for custom example placeholder delimiters to mocha plugin\n\n## [2.1.1]\n\n- Bump dev dependencies\n- Move to prettier\n- Move to github actions\n\n## [2.1.0]\n\n- Update dependencies\n\n## [2.0.1]\n\n- Fix broken requires. See https://github.com/acuminous/yadda/pull/244. Thanks [nonlux](https://github.com/nonlux)\n\n## [2.0.0]\n\n- Fixes [bug](https://github.com/acuminous/yadda/issues/#243)\n- No longer testing on node 4 and 5\n\n## [1.5.1]\n\n- Update dependencies\n- Remove examples with insecure depenencies\n\n## [1.5.0]\n\n- Add support of programatically skipping mocha tests when using the step level plugin\n- Fix examples in npm 5\n\n## [1.4.0]\n\n- Updated more dev deps including browserify\n\n## [1.3.1]\n\n- Updated dev dependencies\n- Automated codeclimate\n\n## [1.3.0]\n\n- Ukranian Localisation - thanks [dedmazayukr](https://github.com/dedmazayukr).\n\n## [1.2.0]\n\n- Passing options through localised steps definition. See #232. Thanks [bogus34](https://github.com/bogus34).\n\n## [1.1.1]\n\n- npms didn't pick up the build\n\n## [1.1.0]\n\n- Switching to eslint\n\n## [1.0.0]\n\n- Tidy up\n- Configuring Code Climate\n\n## [0.22.1]\n\n- Fixes [bug](https://github.com/acuminous/yadda/issues/#225) where errors returned by steps in jasmine were swallowed.\n- Removed webdriver examples (webdriver.js is not longer maintained)\n\n## [0.22.0]\n\n- Fixes [bug](https://github.com/acuminous/yadda/issues/223) where errors thrown by synchronous steps were swallowed.\n\n## [0.21.0]\n\n- Converters can yield multiple values\n\n## [0.20.0]\n\n- Working around [this](https://github.com/mochajs/mocha/issues/2465) issue with mocha 3.\n\n## [0.19.0]\n\n- Removed dist from npm package\n\n## [0.18.0]\n\n- Closes #217 (using catch with promises)\n- Closes #216 (improves step sync/async detection)\n\n## [0.17.10]\n\n- GLOBAL is dead. Long live global. Fixes [#215](https://github.com/acuminous/yadda/issues/215)\n\n## [0.17.9]\n\n- Registering in bower repo.\n\n## [0.17.8]\n\n- Adding the ability to report unused steps. See the report-unused-steps-example.\n\n## [0.17.7]\n\n- [simonihmig](https://github.com/simonihmig) reported and fixed a bug with the step selection routines which caused different behaviour in chrome and phantom.\n\n## [0.17.6]\n\n- Fixing a bug where the interpreter wasn't favoring an ambiguous step from the same library as the previous step\n\n## [0.17.5]\n\n- Supports mixed async and sync - Thanks [chrisns](https://github.com/chrisns)\n- Steps can return promises - Thanks [chrisns](https://github.com/chrisns)\n- Stopped casper integration throwing an exception when path module could not be found\n\n## [0.17.4]\n\n- Fixing a typo\n\n## [0.17.3]\n\n- Configurable placeholder characters used in example tables. Requested in [#203](https://github.com/acuminous/yadda/issues/203)\n\n## [0.17.2]\n\n- Karma support courtesy of [inf3rno](https://github.com/inf3rno). Thanks very much.\n- Removed NODE_ENV=test which caused failures on windows.\n\n## [0.17.1]\n\n- Chinese Localisation - thanks [snowyu](https://github.com/snowyu).\n\n## [0.17.0]\n\n- Fixed a [bug](https://github.com/acuminous/yadda/issues/188) which discarded blank lines at the end of a multline step. If the scenario had multiple multline steps, then an ending blank line in the first step, was injected into the second step.\n\n## [0.16.3]\n\n- Fixed a [bug](https://github.com/acuminous/yadda/issues/187) introduced in 0.16.2 which meant Yadda picked the more undesirable step when two step implementations in the same library matches the step text.\n\n## [0.16.2]\n\n- When yadda find two matching steps with the same Levenshtein distance, it will prefer the one defined in the same library as the previous step.\n\n## [0.16.1]\n\n- Removed bind so phantom works without polyfill\n\n## [0.16.0]\n\n- Outer borders on data tables are ignored\n\n## [0.15.5]\n\n- Fixed but with the mocha ScenarioLevelPlugin which cased all tests to timeout\n\n## [0.15.4]\n\n- Dutch language support courtesy of [https://github.com/remkoboschker](remkoboschker). Thanks.\n\n## [0.15.3]\n\n- Step name included in context automatically courtesy of [remkoboschker](https://github.com/remkoboschker). Thanks.\n\n## [0.15.2]\n\n- Multiline Steps and data-table converters (multiline data tables are still a work in progress)\n- Protractor example courtesy of [mgijsbertihodenpijl])[https://github.com/mgijsbertihodenpijl]. Thanks\n\n## [0.15.1]\n\n- Converted README into a gitbook\n- Fixed a minor bug with example tables\n\n## [0.15.0]\n\n- Breaking Change: Multiline steps in scenarios and backgrounds\n\n## [0.14.2]\n\n- Example table meta fields for incorporating index, line and column values into your scenarios.\n\n## [0.14.1]\n\n- Dictionary converters can take multilpe arguments.\n\n## [0.14.0]\n\n- Dictionaries can be used to convert arguments into arbitary types. Integer, float and date converters are provided out of the box.\n\n## [0.13.1]\n\n- Fixes an issues where the new Annotations class broke moonraker\n\n## [0.13.0]\n\n- An amazing amount of work adding multiline example tables be [thr0w](http://github.com/thr0w).\n- [thr0w](http://github.com/thr0w) also added annotation support to example tables.\n- Breaking Change: In reworking some of [thr0w's](http://github.com/thr0w) example table code we added a breaking change around example table formating. You'll only notice if you centered column headings. If this feature is important to you then we suggest adding column separators to the outer left and right edges table, e.g.\n\n```\n|   one  |   two   |  three  |\n| banana | orange  | apricot |\n```\n\n- Breaking Change: Annotations have been reworked into a class. If you access annotations you need to do so via the get method\n\n```js\n// Instead of\nfeature.annotations.pending;\n// Do\nfeature.annotations.get('pending');\n```\n\nAnnotations can be requested using any case but are stored internally in lowercase. It is not longer valid for annotation names to contain spaces and non alhpanumerics are no longer converted to an underscore.\n\n- Breaking Change: Removed deprecated mocha plugin\n- Breaking Change: Background can no longer have descriptions\n- If you're using a recent version of mocha in combination with the StepLevelPlugin aborted steps will be marked as Pending.\n\n## [0.12.1]\n\n- Adding @Only support to jasmine plugin\n\n## [0.12.0]\n\n- Removing deprecated mocha plugin.\n- Allow the default language to be overriden. See https://github.com/acuminous/yadda/issues/102.\n\n## [0.11.7]\n\n- Portuguese language support courtesy of [https://github.com/thr0w](thr0w). Thanks.\n\n## [0.11.6]\n\n- Added console.log to request user feedback on whether [background descriptions](https://github.com/acuminous/yadda/issues/146) can be decprecated\n- Improved examples\n\n## [0.11.5]\n\n- Russian language support kindly contributed by [vectart](https://github.com/vectart)\n\n## [0.11.4]\n\n- Added a friendlier syntax\n\n## [0.11.3]\n\n- Node is fixed. Removing warning about failing travis build from readme\n\n## [0.11.2]\n\n- Fix for [issue 120](https://github.com/acuminous/yadda/issues/120) - False positives with the new StepLevelPlugin\n\n## [0.11.1]\n\n- Scenarios created from example tables no longer share annotations. See [PR #119](https://github.com/acuminous/yadda/pull/119)\n\n## [0.11.0]\n\n- Removal of scenario descriptions which forced a blank line between scenario title and steps. See [issue #55](https://github.com/acuminous/yadda/issues/55)\n- Deprecation of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin, SyncStepLevelPlugin. Use the new ScenarioLevelPlugin or StepLevelPlugin replacements instead\n- Improved readme - Thanks [prokls](https://github.com/prokls)\n\n## [0.10.14]\n\n- Adding German language support - Thanks [prokls](https://github.com/prokls)\n\n## [0.10.13]\n\n- Locking down the webdriver examples to 2.41.x as (problems)[https://github.com/acuminous/yadda/issues/105] where reported with 2.42\n\n## [0.10.12]\n\n- Adds support for mocha's only feature to the Mocha plugin - see [issue-98](https://github.com/acuminous/yadda/issues/98)\n\n## [0.10.11]\n\n- Fixes [issue-97](https://github.com/acuminous/yadda/issues/97) - scenario annotations after a background caused the parser to fail.\n\n## [0.10.10]\n\n- Added a really basic example\n- Added jshint\n\n## [0.10.9]\n\n- Fix for [issue-93](https://github.com/acuminous/yadda/issue/93). Thanks [simoami](https://github.com/simoami)\n\n## [0.10.8]\n\n- Fix for [issue-88](https://github.com/acuminous/yadda/issues/88)\n- Removal of incorrect French translation for 'background'\n\n## [0.10.7]\n\n- The new mocha plugins can be passed a custom parser\n- Polish language support - Thanks [macie](https://github.com/macie)\n- A fix for multiline commments\n\n## [0.10.6]\n\n- Fix for [issue-82](https://github.com/acuminous/yadda/issues/82)\n- Jasmine webdriver example\n\n## [0.10.5]\n\n- Supporting multiple variations of Pending annotation. See [issue 78](https://github.com/acuminous/yadda/issues/78)\n\n## [0.10.4]\n\n- Annotations can now be prefixed with a space. See [issue79](https://github.com/acuminous/yadda/issues/79)\n\n## [0.10.3]\n\n- The webdriver example uses new mocha plugin\n\n## [0.10.2]\n\n- Fixes to the mocha-sync and mocha-express examples\n- Bower support - Thanks [jeffreytgilbert](http://github.com/jeffreytgilbert)\n- Improved French localisation - Thanks [poum](http://github.com/poum)\n- Improved README - Thanks [gblosser42](http://github.com/gblosser42)\n\n## [0.10.1]\n\n- Improved nodejs detection - Thanks [eXon](http://github.com/eXon)\n\n## [0.10.0]\n\n- Added support for backgrounds - Thanks [mucsi](http://github.com/mucsi)\n- Added support for step level output in mocha tests - Thanks [simoami](http://github.com/simoami)\n- Fixed a few minor bugs in the FeatureParser\n- This release involves a complete rewrite of the mocha/jasmine plugin. The old plugin will be deprecated in 0.12.0.\n  The replacement syntax is:\n\n```\nvar Yadda = require('yadda');\nYadda.plugins.mocha.AsyncScenarioLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function(file) {\n\n    // Previously features(file, function(feature))\n    featureFile(file, function(feature) {\n\n        var library = require('./bottles-library');\n        var yadda = new Yadda.Yadda(library);\n\n        scenarios(feature.scenarios, function(scenario, done) {\n            yadda.yadda(scenario.steps, done);\n        });\n    });\n});\n```\n\nTo get step level output use SyncStepLevelPlugin or AsyncStepLevelPlugin as appropriate, e.g.\n\n```\nvar Yadda = require('yadda');\nYadda.plugins.mocha.AsyncStepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function(file) {\n\n    // Previously features(file, function(feature))\n    featureFile(file, function(feature) {\n\n        var library = require('./bottles-library');\n        var yadda = new Yadda.Yadda(library);\n\n        scenarios(feature.scenarios, function(scenario) {\n            steps(scenario.steps, function(step, done) {\n                yadda.yadda(step, done);\n            })\n        });\n    });\n});\n```\n\n## [0.9.11]\n\n- Updated French translations - Thanks [poum](https://github.com/poum)\n\n## [0.9.10]\n\n- You can use Scenario and Scenario Outline interchangeably\n\n## [0.9.9]\n\n- Added an example using mocha and express\n\n## [0.9.8]\n\n- Added support for component - thanks [johntron](https://github.com/johntron).\n\n## [0.9.7]\n\n- Spanish localisation - thanks [feliun](https://github.com/feliun).\n\n## [0.9.6]\n\n- Fix for [issue 43 - @Pending not working](https://github.com/acuminous/yadda/issues/43)\n- Improvements to French localsation and examples - thanks [ami44](https://github.com/ami44).\n\n## [0.9.5]\n\n- Added Zombie JS example\n- Added Multi library example\n- Generally improved other examples\n\n## [0.9.4]\n\n- Added FeatureFileSearch as discussed in https://github.com/acuminous/yadda/issues/47\n- Using npm link to install yadda for the examples\n- Yadda now lists undefined and ambiguous steps as discussed in https://github.com/acuminous/yadda/issues/30\n\n## [0.9.3]\n\n- French localisation for example tables - thanks [ami44](https://github.com/ami44).\n\n## [0.9.2]\n\n- Added package.json to the example projects so than can be run with `npm install; npm test`\n\n## [0.9.1]\n\n- French Localisation - thanks [ami44](https://github.com/ami44).\n\n## [0.9.0]\n\n- Adds support for example tables\n- Fixes a bug in the MochaPlugin which didn't recognise non English @Pending annotations on scenarios\n- Adds both original and lowercase annotations to the feature / scenarios, so that code which accesses them looks more normal\n\n## [0.8.6]\n\n- Fixes bug in qunit example contributed by [RaulMB](https://github.com/RaulMB\n\n## [0.8.5]\n\n- Fixes to localisation contributed by [kjell](https://github.com/kjelloe).\n\n## [0.8.4]\n\n- Improvements to localisation suggested by [kjell](https://github.com/kjelloe).\n\n## [0.8.3]\n\n- Adds a FileSearch class so you can slurp feature files by directory and pattern instead of having to explicitly list them in your tests.\n\n## [0.8.2]\n\n- Fixeds a bug in the mocha plugin output\n\n## [0.8.1]\n\n- Any text between a Feature line and a Scenario line is ignored.\n- Added support for multiline comments\n- Norwegian Localisation - thanks [kjelloe](https://github.com/kjelloe).\n\n## [0.8.0]\n\n- FeatureParser can be localised. Unfortunately this involved a breaking change to the Yadda.localisation.English API.\n  Thankfully the adjustment is simple.\n\n```js\n// Old Code (< 0.8.0)\nvar library = new Yadda.localisation.English(optional_dictionary);\n\n// New Code  (>= 0.8.0)\nvar library = Yadda.localisation.English.library(optional_dictionary);\n```\n\n## [0.7.2]\n\n- FeatureParser supports single line comments (any line where the first non whitespace character is #)\n\n## [0.7.1]\n\n- Localised libraries slurp whitespace from the start of steps [Pull 31](https://github.com/acuminous/yadda/pull/31). Thanks [Hans](https://github.com/hans-d).\n\n## [0.7.0]\n\n- TextParser renamed to FeatureParser as per [Issue 12](https://github.com/acuminous/yadda/issues/12).\n- StepParser added\n\n## [0.6.5]\n\n- Dictionaries can now be merged\n\n## [0.6.4]\n\n- This release adds jasmine examples\n\n## [0.6.3]\n\n- This release adds selenium / webdriver examples, based on those created by [mrwiggles](https://github.com/mrwiggles) for [Issue 18](https://github.com/acuminous/yadda/issues/18).\n\n## [0.6.2]\n\n- This release adds support for annotations on scenarios. Theses were previously only available on features. Support for simple annoations, e.g. @Pending, is also included.\n\n## [0.6.1]\n\n- Yadda now throws Error objects instead of Strings. See [Issue #24](https://github.com/acuminous/yadda/issues/24).\n\n## [0.6.0]\n\n- Fix for [Issue #23](https://github.com/acuminous/yadda/issues/23) which prevented the scenario context being shared between steps when using the Mocha plugin. The plugin API was made clearer at the same time, which unfortunately necessitated breaking changes. The following demonstrates how to migrate < 0.6 mocha tests to the 0.6 api.\n\n&lt; 0.6.0\n\n```js\nvar Yadda = require('yadda');\nYadda.plugins.mocha();\nvar library = require('./bottles-library');\nvar yadda = new Yadda.Yadda(library);\n\nyadda.mocha('Bottles', './spec/bottles-spec.txt');\n```\n\n&gt;= 0.6.0\n\n```js\nvar Yadda = require('yadda');\nYadda.plugins.mocha();\n\nfeature('./features/bottles.feature', function (feature) {\n  var library = require('./bottles-library');\n  var yadda = new Yadda.Yadda(library);\n\n  scenarios(feature.scenarios, function (scenario, done) {\n    yadda.yadda(scenario.steps, done);\n  });\n});\n```\n\n## [0.5.2]\n\n- Adds annoations to features in feature files. Thanks [mrwiggles](https://github.com/mrwiggles).\n\n## [0.5.1]\n\n- Yadda now emits events, which can be useful for debugging. See the README.md for more details.\n\n## [0.5.0]\n\n- This adds the feature title to the output from the text parser contributed by [akikhtenko](https://github.com/akikhtenko) (thanks). Since this changes the object structure returned by TextParser.parse() if you're using the TextParser directly rather than via the Mocha or Casper plugins, it's a breaking change, but the change is very minor...\n\n```js\nvar scenarios = parser.parse(text); // < 0.5.0\nvar scenarios = parser.parse(text).scenarios; // >= 0.5.0\n```\n\n## [0.4.7]\n\n- The stable version of casperjs is no longer recommended by the casperjs author. It's also problematic to require modules. The latest version of casperjs (installed from master after 13th September 2013) fixes these problems, so I've updated the example to reflect this.\n\n## [0.4.6]\n\n- Accepted pull request for feature blocks. See [Issue 8](https://github.com/acuminous/yadda/pull/8). Thanks [mrwiggles](https://github.com/mrwiggles).\n\n## [0.4.5]\n\n- Fixed scenario parsing on windows bug. See [Issue 6](https://github.com/acuminous/yadda/issues/6). Thanks [grofit](https://github.com/grofit).\n\n## [0.4.4]\n\n- Changed the CasperPlugin API\n\n## [0.4.3]\n\n- Changed the MochaPlugin API\n\n## [0.4.2]\n\n- TextParser no longer maintains state between parses\n\n## [0.4.1]\n\n- Stopped pending asynchronous steps hanging the test run\n- Added mocha plugin\n\n## [0.4.0]\n\n- Yadda now supports both asynchronous and synchronous usage\n- Deleted the before and after hook (after cannot be guaranteed to run when asynchronous)\n\n### Breaking API Changes\n\n#### Removal of before and after hooks\n\nThe before and after hooks have been removed because after cannot be guaranteed to run when yadda\nis asynchronous. Use your test runner's before and after mechanism instead.\n\n#### Removal of non-object contexts\n\nYou can no longer pass non-object contexts to yadda, i.e. instead of...\n\n```js\nlibrary.define('blah blah blah') function() {\n    this.assert();\n});\nnew Yadda(library).('blah blah blah', test);\n```\n\nDo...\n\n```js\nlibrary.define('blah blah blah') function() {\n    this.test.assert();\n});\nnew Yadda(library).('blah blah blah', { test: test });\n```\n\n## [0.3.0]\n\n- Re-implemented as a nodejs module\n- Used browserify for compatability with browser test frameworks like qunit\n\n### Breaking API Changes\n\nYadda has been re-implemented as a nodejs module. This means that the\nglobal 'Yadda' prefixed class names are no longer exposed and that\nall Yadda classes must be explicitly 'required'\n\nIn a node environment this is straightforward...\n\n```\nnpm install yadda\n```\n\n```js\nvar Yadda = require('yadda').Yadda;\nvar Library = require('yadda').Library;\n\nvar library = new Library();\nlibrary.given('$NUM bottles of beer', function (n) {\n  console.log(n + ' ' + 'bottles of beer');\n});\nnew Yadda(library).yadda('100 bottles of beer');\n```\n\nThanks to browserify it straightforward from a browser environment too...\n\n```html\n<head>\n  <script src=\"http://www.github.com/acuminous/yadda/dist/yadda-0.3.0.js\"></script>\n  <script type=\"text/javascript\">\n    var Yadda = require('yadda').Yadda;\n    var Library = require('yadda').Library;\n\n    var library = new Library();\n    library.given('$NUM bottles of beer', function (n) {\n      console.log(n + ' ' + 'bottles of beer');\n    });\n    new Yadda(library).yadda('100 bottles of beer');\n  </script>\n</head>\n```\n\nIn a CasperJS environment it's less straightforward. We haven't found how to get casper to\nunderstand commonjs or umd node modules and Casper's 'require' function clashes with the one created by browserify. For the moment we're working around this with the following ugly hack...\n\n```\nvar oldRequire = require;\nphantom.injectJs('../../dist/yadda-0.3.0.js');\nwindow.Yadda = require('yadda').Yadda;\nwindow.CasperPlugin = require('yadda').plugins.CasperPlugin;\nwindow.Library = require('yadda').Library;\nwindow.require = oldRequire;\n\nlibrary.given('$NUM bottles of beer', function(n) {\n  console.log(n + ' ' + 'bottles of beer');\n};\nvar yadda = new Yadda(library).yadda('100 bottles of beer');\ncasper = new CasperPlugin(yadda, casper).init();\n```\n\n## Yadda 0.2.2\n\n- Added a feature file parser\n- Improved documentation and examples\n\n## Yadda 0.2.1\n\n- Added a CoffeeScript example\n- Added a Nodeunit example\n- Added a Mocha example\n- Added a new context variable to the interpret method. See Nodeunit example for usage.\n- Ensured that Yadda.after is called even if an error occurs\n- Fixed distance_table typo\n\n## Yadda 0.2.0\n\n### Breaking API Changes\n\nIn Yadda 0.1.0 you invoked yadda with\n\n```js\nnew Yadda(steps).yadda(['some scenario']);\n```\n\nThe equivalent syntax in 0.2.2 is\n\n```js\nnew Yadda.yadda(library).yadda(['some scenario']);\n```\n\nwhere library is an instance of Yadda.Library\n\n#### Combining Steps / Libraries\n\n```js\nvar steps = new Steps();\nsteps.importSteps(other_steps);\nvar yadda = new Yadda(steps);\n```\n\nNow you pass yadda an array of libraries instead of a single merged one\n\n```js\nvar lib1 = new Yadda.Library();\nvar lib2 = new Yadda.Library();\nvar yadda = new Yadda().yadda([lib1, lib2]);\n```\n\nalternatively you can do\n\n```js\nvar yadda = new Yadda.yadda();\nyadda.requires(lib1);\nyadda.requires(lib2);\n```\n\nor\n\n```js\nvar yadda = new Yadda.yadda();\nyadda.requires([lib1, lib2]);\n```\n\n#### Defining Steps\n\nPreviously you defined steps using the addStep method, or a given, when, then helper method, e.g.\n\n```js\nsteps.addStep('some text', function () {\n  // some code\n});\n```\n\nStep.addStep has been replaced with Library.define\n\n```js\nlibrary.define('some text', function () {\n  // some code\n});\n```\n\nThe helper methods are no longer available by default, but you can restore them by including yadda-0.2.2-localisation.js and creating your libraries as instances of Yadda.Library.English, e.g.\n\n```js\nvar library = Yadda.Library.English.library()\n  .given('a (\\\\d+) green bottles', function () {\n    // some code\n  })\n  .when('(\\\\d+) falls', function () {\n    // some code\n  })\n  .then('there are (\\\\d+) green bottles', function () {\n    // some code\n  });\n```\n"
  },
  {
    "path": "README.md",
    "content": "# Yadda\n\n[![Gitter](https://badges.gitter.im/acuminous/yadda.svg)](https://gitter.im/acuminous/yadda?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)\n[![NPM version](https://img.shields.io/npm/v/yadda.svg?style=flat-square)](https://www.npmjs.com/package/yadda)\n[![NPM downloads](https://img.shields.io/npm/dm/yadda.svg?style=flat-square)](https://www.npmjs.com/package/yadda)\n[![Node.js CI](https://github.com/acuminous/yadda/workflows/Node.js%20CI/badge.svg)](https://github.com/acuminous/yadda/actions?query=workflow%3A%22Node.js+CI%22)\n[![Code Climate](https://codeclimate.com/github/acuminous/yadda/badges/gpa.svg)](https://codeclimate.com/github/acuminous/yadda)\n[![Test Coverage](https://codeclimate.com/github/acuminous/yadda/badges/coverage.svg)](https://codeclimate.com/github/acuminous/yadda/coverage)\n[![Code Style](https://img.shields.io/badge/code%20style-prettier-brightgreen.svg)](https://github.com/prettier/prettier)\n\nYadda brings _true_ BDD to JavaScript frameworks such as [Jasmine](https://jasmine.github.io/), [Mocha](http://mochajs.org/), [QUnit](http://qunitjs.com), [Nodeunit](https://github.com/caolan/nodeunit), [WebdriverIO](http://webdriver.io/) and [CasperJS](http://casperjs.org). By _true_ BDD we mean that the ordinary language (e.g. English) steps are mapped to code, as opposed to simply decorating it. This is important because just like comments, the decorative steps such as those used by [Jasmine](https://jasmine.github.io/), [Mocha](http://mochajs.org/) and [Vows](http://vowsjs.org) can fall out of date and are a form of duplication.\n\nYadda's BDD implementation is like [Cucumber's](http://cukes.info/) in that it maps the ordinary language steps to code. Not only are the steps less likely to go stale, but they also provide a valuable abstraction layer and encourage re-use. You could of course just use [CucumberJS](https://github.com/cucumber/cucumber-js), but we find Yadda less invasive and prefer its flexible syntax to Gherkin's. Yadda's conflict resolution is smarter too.\n\n## Latest Version\n\nThe current version of Yadda is 2.2.0\n\n## Documentation\n\nPlease refer to the the [Yadda User Guide](http://acuminous.gitbooks.io/yadda-user-guide).\n\n## tl;dr\n\n### Step 1 - Decide upon a directory structure, e.g.\n\n```\n.\n├── bottles-test.js\n├── lib\n│    └── wall.js\n└── test\n    ├── features\n    │   └── bottles.feature\n    └── steps\n        └── bottles-library.js\n```\n\n### Step 2 - Write your first scenario\n\n./test/features/bottles.feature\n\n```\nFeature: 100 Green Bottles\n\nScenario: Should fall from the wall\n\n   Given 100 green bottles are standing on the wall\n   When 1 green bottle accidentally falls\n   Then there are 99 green bottles standing on the wall\n\n```\n\n### Step 3 - Implement the step library\n\n./test/steps/bottles-library.js\n\n```js\nvar assert = require('assert');\nvar English = require('yadda').localisation.English;\nvar Wall = require('../../lib/wall'); // The library that you wish to test\n\nmodule.exports = (function () {\n  return English.library()\n    .given('$NUM green bottles are standing on the wall', function (number, next) {\n      wall = new Wall(number);\n      next();\n    })\n    .when('$NUM green bottle accidentally falls', function (number, next) {\n      wall.fall(number);\n      next();\n    })\n    .then('there are $NUM green bottles standing on the wall', function (number, next) {\n      assert.equal(number, wall.bottles);\n      next();\n    });\n})();\n```\n\n(If your test runner & code are synchronous you can omit the calls to 'next')\n\n### Step 4 - Integrate Yadda with your testing framework (e.g. Mocha)\n\n./bottles-test.js\n\n```js\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('./test/features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./test/steps/bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n```\n\n### Step 5 - Write your code\n\n./lib/wall.js\n\n```js\nmodule.exports = function (bottles) {\n  this.bottles = bottles;\n  this.fall = function (n) {\n    this.bottles -= n;\n  };\n};\n```\n\n### Step 6 - Run your tests\n\n```\n  mocha --reporter spec bottles-test.js\n\n  100 Green Bottles\n    Should fall from the wall\n      ✓ Given 100 green bottles are standing on the wall\n      ✓ When 1 green bottle accidentally falls\n      ✓ Then there are 99 green bottles standing on the wall\n```\n"
  },
  {
    "path": "bin/browserify.js",
    "content": "'use strict';\n\nvar browserify = require('browserify');\nvar path = require('path');\nvar fs = require('fs');\nvar rootpath = process.cwd();\nvar pkg = require(path.join(rootpath, 'package.json'));\n\n(function web_bundle() {\n  var bundle = fs.createWriteStream(path.join(rootpath, 'dist', 'yadda-' + pkg.version + '.js'));\n\n  var b = browserify();\n  b.add('./lib/index.js');\n  b.require('./lib/index.js', { expose: 'yadda' });\n  b.ignore('casper');\n  b.bundle().pipe(bundle);\n})();\n\n(function umd_bundle() {\n  var bundle = fs.createWriteStream(path.join(rootpath, 'dist', 'yadda-umd-' + pkg.version + '.js'));\n\n  var b = browserify();\n  b.add('./lib/index.js');\n\n  b.require('./lib/index.js', { expose: 'yadda' });\n  b.ignore('casper');\n\n  b.bundle().pipe(bundle);\n})();\n"
  },
  {
    "path": "bin/examples.bat",
    "content": "@echo off\nsetlocal\n\n:run\ncall npm link\npushd examples\nfor /d %%D in (*.*) do echo Running %%D example & pushd %%D & call npm --loglevel error install & call npm test & popd\npopd\n\nendlocal\n"
  },
  {
    "path": "bin/examples.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\examples.bat' : 'bin/examples.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "bin/examples.sh",
    "content": "#!/bin/bash\n\nset -e\n\nnpm link\npushd examples\nfor D in *; do\n    echo \"Running ${D} example\"\n    pushd ${D}\n    npm --loglevel error install\n    npm test\n    popd\ndone\npopd\n"
  },
  {
    "path": "bin/rev.sh",
    "content": "#!/bin/bash\nset -e\n\nVERSION_PATTERN=[0-9]+\\\\.[0-9]+\\\\.[0-9]+\nVERSION=$1\n\nif [ -z \"$VERSION\" ]; then\n    echo \"usage: rev <VERSION>\"\n    exit 1\nfi\n\nnpm run lint\nnpm test\nnpm run karma\n\nsed -i '' -E \"s/\\\"version\\\": \\\"$VERSION_PATTERN\\\"/\\\"version\\\": \\\"$VERSION\\\"/\" package.json\nsed -i '' -E \"s/\\\"version\\\": \\\"$VERSION_PATTERN\\\"/\\\"version\\\": \\\"$VERSION\\\"/\" component.json\nsed -i '' -E \"s/\\\"version\\\": \\\"$VERSION_PATTERN\\\"/\\\"version\\\": \\\"$VERSION\\\"/\" bower.json\nsed -i '' -E \"s/The current version of Yadda is $VERSION_PATTERN/The current version of Yadda is $VERSION/\" README.md\nsed -i '' -E \"s/yadda-$VERSION_PATTERN.js/yadda-$VERSION.js/\" README.md\nsed -i '' -E \"s/Yadda $VERSION_PATTERN/Yadda $VERSION/\" lib/Yadda.js\nsed -i '' -E \"s/yadda-$VERSION_PATTERN.js/yadda-$VERSION.js/\" examples/qunit/test.html\n\nnpm run browserify\nnpm run examples\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"yadda\",\n  \"version\": \"2.2.0\",\n  \"homepage\": \"https://github.com/acuminous/yadda\",\n  \"description\": \"A true BDD framework for JavaScript\",\n  \"main\": \"lib/index.js\",\n  \"moduleType\": [\"node\"],\n  \"keywords\": [\"BDD\", \"Specification\", \"Natural\", \"Test\", \"Behaviour\", \"Driven\", \"Jasmine\", \"Mocha\", \"QUnit\", \"Nodeunit\"],\n  \"authors\": [\"Stephen Cresswell\"],\n  \"license\": \"Apache2\",\n  \"ignore\": [\"**/.*\", \"node_modules\", \"bower_components\", \"test\", \"tests\"]\n}\n"
  },
  {
    "path": "component.json",
    "content": "{\n  \"name\": \"yadda\",\n  \"version\": \"2.2.0\",\n  \"description\": \"A true BDD framework for JavaScript\",\n  \"repo\": \"acuminous/yadda\",\n  \"keywords\": [\"BDD\", \"Specification\", \"Natural\", \"Test\", \"Behaviour\", \"Driven\", \"Jasmine\", \"Mocha\", \"QUnit\", \"Nodeunit\"],\n  \"main\": \"lib/index.js\",\n  \"scripts\": [\n    \"lib/StringUtils.js\",\n    \"lib/Array.js\",\n    \"lib/Competition.js\",\n    \"lib/Context.js\",\n    \"lib/converters/date-converter.js\",\n    \"lib/converters/float-converter.js\",\n    \"lib/converters/index.js\",\n    \"lib/converters/integer-converter.js\",\n    \"lib/converters/pass-through-converter.js\",\n    \"lib/Dictionary.js\",\n    \"lib/EventBus.js\",\n    \"lib/FileSearch.js\",\n    \"lib/FeatureFileSearch.js\",\n    \"lib/fn.js\",\n    \"lib/index.js\",\n    \"lib/Interpreter.js\",\n    \"lib/LevenshteinDistanceScore.js\",\n    \"lib/Library.js\",\n    \"lib/localisation/English.js\",\n    \"lib/localisation/French.js\",\n    \"lib/localisation/German.js\",\n    \"lib/localisation/index.js\",\n    \"lib/localisation/Language.js\",\n    \"lib/localisation/Pirate.js\",\n    \"lib/localisation/Polish.js\",\n    \"lib/localisation/Russian.js\",\n    \"lib/localisation/Spanish.js\",\n    \"lib/localisation/Norwegian.js\",\n    \"lib/localisation/Portuguese.js\",\n    \"lib/Macro.js\",\n    \"lib/parsers/FeatureParser.js\",\n    \"lib/parsers/FeatureFileParser.js\",\n    \"lib/parsers/StepParser.js\",\n    \"lib/parsers/index.js\",\n    \"lib/Platform.js\",\n    \"lib/plugins/CasperPlugin.js\",\n    \"lib/plugins/index.js\",\n    \"lib/plugins/mocha/ScenarioLevelPlugin.js\",\n    \"lib/plugins/mocha/StepLevelPlugin.js\",\n    \"lib/plugins/mocha/BasePlugin.js\",\n    \"lib/RegularExpression.js\",\n    \"lib/shims/index.js\",\n    \"lib/Yadda.js\"\n  ],\n  \"development\": {\n    \"visionmedia/mocha\": \"*\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\",\n  \"readmeFilename\": \"README.md\"\n}\n"
  },
  {
    "path": "dist/yadda-0.10.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_node()) return global; \n        if (is_phantom()) return phantom;\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '[Ff]ond',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_node()) return shims.node();\n\n        if (platform.is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '[Ff]ond',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.10.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.10 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');\n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.11.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.11 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');\n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.12.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.12 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.13.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.13 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.14.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.14 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":26,\"./parsers/index\":30,\"./plugins/index\":33,\"./shims/index\":39}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":21}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":21}],20:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":21}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],22:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":21}],24:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":21}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":21}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./German\":20,\"./Language\":21,\"./Norwegian\":22,\"./Pirate\":23,\"./Polish\":24,\"./Spanish\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":28,\"fs\":44}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":27,\"./FeatureParser\":28,\"./StepParser\":29}],31:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":44,\"yadda\":\"3V0FPO\"}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":28,\"fs\":44}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":31,\"./MochaPlugin\":32,\"./mocha/AsyncScenarioLevelPlugin\":34,\"./mocha/AsyncStepLevelPlugin\":35,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":27}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],39:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"__browserify_process\":47,\"fs\":44,\"path\":45}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":44,\"path\":45}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":44}],43:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],44:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],45:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":47,\"_shims\":43,\"util\":46}],46:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":43}],47:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.6.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            console.log(step);\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });        \n    }     \n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.7.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given },\n        get majac() { return this.given },\n        get jezeli() { return this.when },\n        get jesli() { return this.when },\n        get gdy() { return this.when },\n        get kiedy() { return this.when },\n        get wtedy() { return this.then }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],29:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            console.log(step);\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });        \n    }     \n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.8.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.8 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given },\n        get majac() { return this.given },\n        get jezeli() { return this.when },\n        get jesli() { return this.when },\n        get gdy() { return this.when },\n        get kiedy() { return this.when },\n        get wtedy() { return this.then }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    function validate() {\n        if (scenarios.length == 0) throw new Error('Feature requires one or more scenarios');        \n    };    \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],29:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            console.log(step);\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });        \n    }     \n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.10.9.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.9 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given },\n        get majac() { return this.given },\n        get jezeli() { return this.when },\n        get jesli() { return this.when },\n        get gdy() { return this.when },\n        get kiedy() { return this.when },\n        get wtedy() { return this.then }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    function validate() {\n        if (scenarios.length == 0) throw new Error('Feature requires one or more scenarios');        \n    };    \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],29:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });        \n    }     \n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.11.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":45}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.11.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":26,\"fs\":43}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":43,\"yadda\":undefined}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":26,\"fs\":43}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n    var abort;\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            abort = false;\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n    }\n\n    function step_async(step, iterator) {\n        base_plugin.it_async(step, step, function(step, done) {\n            if (abort) return done();\n            abort = true;\n            iterator(step, function(err) {\n                if (err) return done(err);\n                abort = false;\n                done();\n            });\n        });\n    }\n\n    function step_sync(step, iterator) {\n        base_plugin.it_sync(step, step, function(step) {\n            if (abort) return;\n            abort = true;\n            iterator(step);\n            abort = false;\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],39:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"_process\":45,\"fs\":43,\"path\":44}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],43:[function(require,module,exports){\n\n},{}],44:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":45}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":39}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-0.11.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":41}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},__dirname=\"/\";/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{\"__browserify_process\":49}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.11.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":26,\"./parsers/index\":30,\"./plugins/index\":33,\"./shims/index\":41}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":21}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":21}],20:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":21}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],22:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":21}],24:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":21}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":21}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./German\":20,\"./Language\":21,\"./Norwegian\":22,\"./Pirate\":23,\"./Polish\":24,\"./Spanish\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":28,\"fs\":46}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":27,\"./FeatureParser\":28,\"./StepParser\":29}],31:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":46,\"yadda\":\"3V0FPO\"}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":28,\"fs\":46}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":31,\"./MochaPlugin\":32,\"./mocha/AsyncScenarioLevelPlugin\":34,\"./mocha/AsyncStepLevelPlugin\":35,\"./mocha/ScenarioLevelPlugin\":37,\"./mocha/StepLevelPlugin\":38,\"./mocha/SyncScenarioLevelPlugin\":39,\"./mocha/SyncStepLevelPlugin\":40}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":27}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n    var abort;\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            abort = false;\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n    }\n\n    function step_async(step, iterator) {\n        base_plugin.it_async(step, step, function(step, done) {\n            if (abort) return done();\n            abort = true;\n            iterator(step, function(err) {\n                if (err) return done(err);\n                abort = false;\n                done();\n            });\n        });\n    }\n\n    function step_sync(step, iterator) {\n        base_plugin.it_sync(step, step, function(step) {\n            if (abort) return;\n            abort = true;\n            iterator(step);\n            abort = false;\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],41:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":42,\"./phantom-path\":43,\"./phantom-process\":44,\"__browserify_process\":49,\"fs\":46,\"path\":47}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],45:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],46:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],47:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":49,\"_shims\":45,\"util\":48}],48:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":45}],49:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.11.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":45}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.11.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":26,\"fs\":43}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":43,\"yadda\":undefined}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":26,\"fs\":43}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],39:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"_process\":45,\"fs\":43,\"path\":44}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],43:[function(require,module,exports){\n\n},{}],44:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":45}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":39}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-0.11.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":45}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.11.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":26,\"fs\":43}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":43,\"yadda\":undefined}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":26,\"fs\":43}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],39:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"_process\":45,\"fs\":43,\"path\":44}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],43:[function(require,module,exports){\n\n},{}],44:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":45}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":39}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-0.11.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":45}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.11.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":26,\"fs\":43}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":43,\"yadda\":undefined}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":26,\"fs\":43}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],39:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"_process\":45,\"fs\":43,\"path\":44}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],43:[function(require,module,exports){\n\n},{}],44:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":45}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":39}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-0.11.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":40}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":46}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.11.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Russian\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":44}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":44,\"yadda\":undefined}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":27,\"fs\":44}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/ScenarioLevelPlugin\":36,\"./mocha/StepLevelPlugin\":37,\"./mocha/SyncScenarioLevelPlugin\":38,\"./mocha/SyncStepLevelPlugin\":39}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],40:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":41,\"./phantom-path\":42,\"./phantom-process\":43,\"_process\":46,\"fs\":44,\"path\":45}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":44,\"path\":45}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":44}],44:[function(require,module,exports){\n\n},{}],45:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":46}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":40}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-0.11.6.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":4,\"./Dictionary\":5,\"./EventBus\":6,\"./FeatureFileSearch\":7,\"./FileSearch\":8,\"./Interpreter\":9,\"./Library\":11,\"./Platform\":13,\"./Yadda\":15,\"./localisation/index\":26,\"./parsers/index\":30,\"./plugins/index\":33,\"./shims/index\":41}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":2,\"./LevenshteinDistanceScore\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":2,\"./RegularExpression\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":2,\"./fn\":16}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":2,\"./shims/index\":41}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":2,\"./Competition\":3,\"./Context\":4,\"./EventBus\":6,\"./fn\":16}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":2,\"./Dictionary\":5,\"./Macro\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":4,\"./EventBus\":6,\"./RegularExpression\":14,\"./fn\":16}],13:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":47}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":2}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.11.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":4,\"./Interpreter\":9,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":2,\"../Library\":11}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Russian\":24,\"./Spanish\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":28,\"fs\":45}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: issue146,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function issue146() {\n        if (!FeatureParser.silence146) {\n            console.log(\"It appears that you are using background descriptions that either span\");\n            console.log(\"mutliple lines or begin immediately beneath the 'Background' keyword\");\n            console.log(\"We are considering removing this feature. Please update\");\n            console.log(\"https://github.com/acuminous/yadda/issues/146 if it is important to you\");\n            console.log(\"You can disable this message by setting FeatureParser.silence146 to true\");\n        }\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":2,\"../fn\":16,\"../localisation/English\":17}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":2}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":27,\"./FeatureParser\":28,\"./StepParser\":29}],31:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":45,\"yadda\":\"yadda\"}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":2,\"../localisation/English\":17,\"../parsers/FeatureParser\":28,\"fs\":45}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":31,\"./MochaPlugin\":32,\"./mocha/AsyncScenarioLevelPlugin\":34,\"./mocha/AsyncStepLevelPlugin\":35,\"./mocha/ScenarioLevelPlugin\":37,\"./mocha/StepLevelPlugin\":38,\"./mocha/SyncScenarioLevelPlugin\":39,\"./mocha/SyncStepLevelPlugin\":40}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"../../localisation/English\":17,\"../../parsers/FeatureFileParser\":27}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],41:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":13,\"./phantom-fs\":42,\"./phantom-path\":43,\"./phantom-process\":44,\"_process\":47,\"fs\":45,\"path\":46}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":45}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":45,\"path\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":45}],45:[function(require,module,exports){\n\n},{}],46:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":47}],47:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}]},{},[1]);\n"
  },
  {
    "path": "dist/yadda-0.11.7.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":4,\"./Dictionary\":5,\"./EventBus\":6,\"./FeatureFileSearch\":7,\"./FileSearch\":8,\"./Interpreter\":9,\"./Library\":11,\"./Platform\":13,\"./Yadda\":15,\"./localisation/index\":27,\"./parsers/index\":31,\"./plugins/index\":34,\"./shims/index\":42}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":2,\"./LevenshteinDistanceScore\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":2,\"./RegularExpression\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":2,\"./fn\":16}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":2,\"./shims/index\":42}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":2,\"./Competition\":3,\"./Context\":4,\"./EventBus\":6,\"./fn\":16}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":2,\"./Dictionary\":5,\"./Macro\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":4,\"./EventBus\":6,\"./RegularExpression\":14,\"./fn\":16}],13:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":2}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.11.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":4,\"./Interpreter\":9,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":2,\"../Library\":11}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue)',\n        then: '(?:[Ee]nt[aã]o)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Portuguese\":24,\"./Russian\":25,\"./Spanish\":26}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":29,\"fs\":46}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: issue146,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function issue146() {\n        if (!FeatureParser.silence146) {\n            console.log(\"It appears that you are using background descriptions that either span\");\n            console.log(\"mutliple lines or begin immediately beneath the 'Background' keyword\");\n            console.log(\"We are considering removing this feature. Please update\");\n            console.log(\"https://github.com/acuminous/yadda/issues/146 if it is important to you\");\n            console.log(\"You can disable this message by setting FeatureParser.silence146 to true\");\n        }\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":2,\"../fn\":16,\"../localisation/English\":17}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":2}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":28,\"./FeatureParser\":29,\"./StepParser\":30}],32:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":2,\"../localisation/English\":17,\"../parsers/FeatureParser\":29,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":32,\"./MochaPlugin\":33,\"./mocha/AsyncScenarioLevelPlugin\":35,\"./mocha/AsyncStepLevelPlugin\":36,\"./mocha/ScenarioLevelPlugin\":38,\"./mocha/StepLevelPlugin\":39,\"./mocha/SyncScenarioLevelPlugin\":40,\"./mocha/SyncStepLevelPlugin\":41}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"../../localisation/English\":17,\"../../parsers/FeatureFileParser\":28}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":13,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}]},{},[1]);\n"
  },
  {
    "path": "dist/yadda-0.12.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":4,\"./Dictionary\":5,\"./EventBus\":6,\"./FeatureFileSearch\":7,\"./FileSearch\":8,\"./Interpreter\":9,\"./Library\":11,\"./Platform\":13,\"./Yadda\":15,\"./localisation/index\":27,\"./parsers/index\":31,\"./plugins/index\":33,\"./shims/index\":37}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":2,\"./LevenshteinDistanceScore\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":2,\"./RegularExpression\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":2,\"./fn\":16}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":2,\"./shims/index\":37}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":2,\"./Competition\":3,\"./Context\":4,\"./EventBus\":6,\"./fn\":16}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":2,\"./Dictionary\":5,\"./Macro\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":4,\"./EventBus\":6,\"./RegularExpression\":14,\"./fn\":16}],13:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":43}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":2}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.12.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":4,\"./Interpreter\":9,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":2,\"../Library\":11}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue)',\n        then: '(?:[Ee]nt[aã]o)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Portuguese\":24,\"./Russian\":25,\"./Spanish\":26}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":29,\"fs\":41}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: issue146,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function issue146() {\n        if (!FeatureParser.silence146) {\n            console.log(\"It appears that you are using background descriptions that either span\");\n            console.log(\"mutliple lines or begin immediately beneath the 'Background' keyword\");\n            console.log(\"We are considering removing this feature. Please update\");\n            console.log(\"https://github.com/acuminous/yadda/issues/146 if it is important to you\");\n            console.log(\"You can disable this message by setting FeatureParser.silence146 to true\");\n        }\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":2,\"../fn\":16,\"../localisation\":27}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":2}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":28,\"./FeatureParser\":29,\"./StepParser\":30}],32:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":41,\"yadda\":\"yadda\"}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":32,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"../../localisation\":27,\"../../parsers/FeatureFileParser\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":34}],37:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":13,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"_process\":43,\"fs\":41,\"path\":42}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":41,\"path\":42}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":41}],41:[function(require,module,exports){\n\n},{}],42:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":43}],43:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}]},{},[1]);\n"
  },
  {
    "path": "dist/yadda-0.12.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":36}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":42}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.12.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue)',\n        then: '(?:[Ee]nt[aã]o)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":19}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":19}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Portuguese\":23,\"./Russian\":24,\"./Spanish\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":28,\"fs\":40}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: issue146,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function issue146() {\n        if (!FeatureParser.silence146) {\n            console.log(\"It appears that you are using background descriptions that either span\");\n            console.log(\"mutliple lines or begin immediately beneath the 'Background' keyword\");\n            console.log(\"We are considering removing this feature. Please update\");\n            console.log(\"https://github.com/acuminous/yadda/issues/146 if it is important to you\");\n            console.log(\"You can disable this message by setting FeatureParser.silence146 to true\");\n        }\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation\":26}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":27,\"./FeatureParser\":28,\"./StepParser\":29}],31:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":40,\"yadda\":\"yadda\"}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":31,\"./mocha/ScenarioLevelPlugin\":34,\"./mocha/StepLevelPlugin\":35}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":26,\"../../parsers/FeatureFileParser\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":33}],36:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":37,\"./phantom-path\":38,\"./phantom-process\":39,\"_process\":42,\"fs\":40,\"path\":41}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":40}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":40,\"path\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":40}],40:[function(require,module,exports){\n\n},{}],41:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":42}],42:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":26,\"./parsers/index\":30,\"./plugins/index\":32,\"./shims/index\":36}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.13.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":16}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":16}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":16}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":43}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.13.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Portuguese\":24,\"./Russian\":25,\"./Spanish\":26}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":29,\"fs\":41}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1]);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (index + 1) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.get = function(key) {\n        return annotations[key.toLowerCase()];\n    };\n\n    this.remove = function(key) {\n        delete annotations[key.toLowerCase];\n    };\n\n    this.merge = function(other) {\n        other.each(function(key, value) {\n            annotations[key] = value;\n        });\n        return this;\n    };\n\n    this.each = function(iterator) {\n        for (var key in annotations) {\n            iterator(key, annotations[key]);\n        }\n    };\n\n    this.keys = function() {\n        var result = [];\n        for (var key in annotations) {\n            result.push(key);\n        }\n        return result;\n    };\n\n    this.isEmpty = function() {\n        return this.keys().length === 0;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        headings = split(data).collect(function(column) {\n            return { text: StringUtils.trim(column), indentation: StringUtils.indentation(column) };\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n    }\n\n    function continue_capturing_multiline_fields(event, data) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: example.annotations.merge(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":16,\"../localisation\":27}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":28,\"./FeatureParser\":29,\"./StepParser\":30}],32:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":41,\"yadda\":\"yadda\"}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":32,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        return $(annotations && annotations.keys()).find(function(key) {\n            return regexp.test(key);\n        });\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":27,\"../../parsers/FeatureFileParser\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"_process\":43,\"fs\":41,\"path\":42}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":41,\"path\":42}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":41}],41:[function(require,module,exports){\n\n},{}],42:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":43}],43:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./localisation/index\":27,\"./parsers/index\":31,\"./plugins/index\":33,\"./shims/index\":37}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.13.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":16}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":16}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":16}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":43}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.13.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Portuguese\":24,\"./Russian\":25,\"./Spanish\":26}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":29,\"fs\":41}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1]);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (index + 1) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        headings = split(data).collect(function(column) {\n            return { text: StringUtils.trim(column), indentation: StringUtils.indentation(column) };\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n    }\n\n    function continue_capturing_multiline_fields(event, data) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":16,\"../localisation\":27}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":28,\"./FeatureParser\":29,\"./StepParser\":30}],32:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":41,\"yadda\":\"yadda\"}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":32,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":27,\"../../parsers/FeatureFileParser\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"_process\":43,\"fs\":41,\"path\":42}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":41,\"path\":42}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":41}],41:[function(require,module,exports){\n\n},{}],42:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":43}],43:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./localisation/index\":27,\"./parsers/index\":31,\"./plugins/index\":33,\"./shims/index\":37}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.14.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (this.is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (is_expandable(pattern) && converters) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && count_matching_groups(pattern) !== $(converters).length) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return !!definitions[term];\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return _this.is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                              : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        args.collect_async(function(arg, index, callback) {\n            parsed_signature.converters[index](arg, callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.14.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1]);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (index + 1) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        headings = split(data).collect(function(column) {\n            return { text: StringUtils.trim(column), indentation: StringUtils.indentation(column) };\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n    }\n\n    function continue_capturing_multiline_fields(event, data) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.14.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.14.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1]);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (index + 1) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        headings = split(data).collect(function(column) {\n            return { text: StringUtils.trim(column), indentation: StringUtils.indentation(column) };\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n    }\n\n    function continue_capturing_multiline_fields(event, data) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.14.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.14.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank', line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.15.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, ' ');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, ' ');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.15.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, ' ');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, ' ');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.15.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":44}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":50}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":48}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":48,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":41}],44:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":45,\"./phantom-path\":46,\"./phantom-process\":47,\"_process\":50,\"fs\":48,\"path\":49}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":48}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":48,\"path\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":48}],48:[function(require,module,exports){\n\n},{}],49:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":50}],50:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":44}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.15.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":44}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":50}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":48}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":48,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":41}],44:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":45,\"./phantom-path\":46,\"./phantom-process\":47,\"_process\":50,\"fs\":48,\"path\":49}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":48}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":48,\"path\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":48}],48:[function(require,module,exports){\n\n},{}],49:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":50}],50:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":44}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.15.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":45}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":51}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":49}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":49,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],45:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":46,\"./phantom-path\":47,\"./phantom-process\":48,\"_process\":51,\"fs\":49,\"path\":50}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":49,\"path\":50}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":49}],49:[function(require,module,exports){\n\n},{}],50:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":51}],51:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":45}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.15.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":45}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":51}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":49}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":49,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],45:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":46,\"./phantom-path\":47,\"./phantom-process\":48,\"_process\":51,\"fs\":49,\"path\":50}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":49,\"path\":50}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":49}],49:[function(require,module,exports){\n\n},{}],50:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":51}],51:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":45}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.16.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":45}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":51}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.16.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":49}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":49,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],45:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":46,\"./phantom-path\":47,\"./phantom-process\":48,\"_process\":51,\"fs\":49,\"path\":50}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":49,\"path\":50}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":49}],49:[function(require,module,exports){\n\n},{}],50:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":51}],51:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":45}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.16.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":45}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":51}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.16.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":49}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":49,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],45:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":46,\"./phantom-path\":47,\"./phantom-process\":48,\"_process\":51,\"fs\":49,\"path\":50}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":49,\"path\":50}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":49}],49:[function(require,module,exports){\n\n},{}],50:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":51}],51:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":45}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.16.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":44,\"./scores/MultiScore\":45,\"./scores/SameLibraryScore\":46}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":47}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":53}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.16.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":27}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":23,\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":51}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":51,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        this.scores.find(fn.curry(null, lesserScore, other));\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function lesserScore(other, score, index) {\n        return score.value > other.scores[index].value;\n    }\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.value > other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],47:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./phantom-fs\":48,\"./phantom-path\":49,\"./phantom-process\":50,\"_process\":53,\"fs\":51,\"path\":52}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":51}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":51,\"path\":52}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":51}],51:[function(require,module,exports){\n\n},{}],52:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":53}],53:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":47}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.16.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":44,\"./scores/MultiScore\":45,\"./scores/SameLibraryScore\":46}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":47}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":53}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.16.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":27}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":23,\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":51}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":51,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],47:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./phantom-fs\":48,\"./phantom-path\":49,\"./phantom-process\":50,\"_process\":53,\"fs\":51,\"path\":52}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":51}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":51,\"path\":52}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":51}],51:[function(require,module,exports){\n\n},{}],52:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":53}],53:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":47}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":44,\"./scores/MultiScore\":45,\"./scores/SameLibraryScore\":46}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":47}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":53}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":27}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":23,\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":51}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":51,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],47:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./phantom-fs\":48,\"./phantom-path\":49,\"./phantom-process\":50,\"_process\":53,\"fs\":51,\"path\":52}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":51}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":51,\"path\":52}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":51}],51:[function(require,module,exports){\n\n},{}],52:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":53}],53:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":47}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":54}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":52}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":52,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./phantom-fs\":49,\"./phantom-path\":50,\"./phantom-process\":51,\"_process\":54,\"fs\":52,\"path\":53}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":52}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":52,\"path\":53}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":52}],52:[function(require,module,exports){\n\n},{}],53:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":54}],54:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.10.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.10 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.isLanguage = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.isLanguage ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.6.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.7.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.8.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.8 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.17.9.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.9 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.18.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.18.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.19.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.19.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.20.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.20.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.21.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.21.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.22.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err)\n                throw err\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.22.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.22.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err)\n                throw err\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.22.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.22.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.22.2 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-0.3.0.js",
    "content": "require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fnUtils = require('./fnUtils');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var before = fnUtils.NO_OP;\n    var after = fnUtils.NO_OP;\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        run(script, environment.merge(ctx));        \n    };\n\n    var run = function(script, env) {\n        fnUtils.invoke(before, env.ctx);\n        try {\n            _this.interpreter.interpret(script, env.ctx);\n        } finally {\n            fnUtils.invoke(after, env.ctx);\n        }        \n    }\n\n    this.before = function(fn) {\n        before = fn;\n        return this;\n    };\n\n    this.after = function(fn) {\n        after = fn;\n        return this;\n    };\n\n    this.toString = function() {\n        \"Yadda 0.3.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fnUtils\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx) {\n        $(scenario).each(function(step) { \n            _this.interpret_step(step, ctx);\n        });\n    };\n\n    this.interpret_step = function(step, ctx) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Dictionary\":4,\"./Macro\":12,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":14}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin')\n}\n},{\"./CasperPlugin\":15}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":16,\"./Pirate\":17}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    function curry(ctx, fn) {\n        var slice = Array.prototype.slice;\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    } ;\n\n    return {\n        NO_OP: function() {},\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],15:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":18,\"./Array\":11}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fnUtils = require('./fnUtils');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, fn, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var fn = fn || fnUtils.NO_OP;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step);\n        return fnUtils.invoke(fn, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fnUtils\":9,\"./Environment\":8,\"./RegularExpression\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fnUtils = require('./fnUtils');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fnUtils.curry(array, in_array, array);\n        array.each = fnUtils.curry(array, each, array);\n        array.collect = fnUtils.curry(array, collect, array);\n        array.flatten = fnUtils.curry(array, flatten, array);\n        array.inject = fnUtils.curry(array, inject, array);\n        array.push_all = fnUtils.curry(array, push_all, array);\n        array.find_all = fnUtils.curry(array, find_all, array);\n        array.find = fnUtils.curry(array, find, array);\n        array.naked = fnUtils.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, fn) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = fn(items[i]);\n        };\n        return result;\n    };\n\n    function collect(items, fn) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(fn(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, fn) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = fn(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fnUtils\":9}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios = [];\n\n    this.parse = function(text) {\n        current_scenario = {};\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}]},{},[\"gUiUAT\"])\n;"
  },
  {
    "path": "dist/yadda-0.4.0.js",
    "content": "require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        \"Yadda 0.4.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./fn\":8,\"./Environment\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Array\":11,\"./Dictionary\":4}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./Pirate\":14,\"./English\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin')\n}\n},{\"./CasperPlugin\":17}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],17:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":18,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":8}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback);        \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":8,\"./Environment\":9,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios = [];\n\n    this.parse = function(text) {\n        current_scenario = {};\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}]},{},[\"gUiUAT\"])\n;"
  },
  {
    "path": "dist/yadda-0.4.1.js",
    "content": "require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Library\":2,\"./Interpreter\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        \"Yadda 0.4.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":3,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":10,\"./Dictionary\":4,\"./Array\":11}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":12,\"./Array\":11,\"./fn\":9}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./Pirate\":14,\"./English\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin'),\n    MochaPlugin: require('./MochaPlugin'),\n    JasminePlugin: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":17,\"./MochaPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":2,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios = [];\n\n    this.parse = function(text) {\n        current_scenario = {};\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],18:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(yadda, feature, filename) {\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(feature, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };        \n    };\n\n    return {\n        feature: feature\n    };\n};\n},{\"fs\":19,\"../parsers/TextParser\":16}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":2,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])\n;"
  },
  {
    "path": "dist/yadda-0.4.2.js",
    "content": "require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Interpreter\":1,\"./Yadda\":2,\"./Library\":3,\"./localisation/index\":4,\"./Dictionary\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":8,\"./Array\":9,\"./fn\":10}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        \"Yadda 0.4.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":11,\"./Interpreter\":1,\"./fn\":10}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":5,\"./Array\":9}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./RegularExpression\":13,\"./Array\":9}],4:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin'),\n    MochaPlugin: require('./MochaPlugin'),\n    JasminePlugin: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":16,\"./MochaPlugin\":17}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":18}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],16:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":10}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":10,\"./Environment\":11,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":9}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":9}],17:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(yadda, feature, filename) {\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(feature, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };        \n    };\n\n    return {\n        feature: feature\n    };\n};\n},{\"fs\":19,\"../parsers/TextParser\":18}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":9}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":9,\"../localisation\":4}]},{},[\"gUiUAT\"])\n;"
  },
  {
    "path": "dist/yadda-0.4.3.js",
    "content": "require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin'),\n    MochaPlugin: require('./MochaPlugin'),\n    JasminePlugin: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":17,\"./MochaPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],18:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = (function() {\n\n    function MochaPlugin(options) {\n\n        var options = options || {};\n        var parser = options.parser || new TextParser();\n        var mode = options.mode || 'async';\n\n        this.upgrade = function(Yadda) {\n\n            function feature(name, filename) {\n\n                var yadda = this;\n\n                var runners = {\n                    async: runAsyncScenario,\n                    asynchronous: runAsyncScenario,\n                    sync: runSyncScenario,\n                    synchronous: runSyncScenario\n                };\n\n                describe(name, function() {            \n                    var text = fs.readFileSync(filename, 'utf8');\n                    try {\n                        var scenarios = parser.parse(text);\n                        runScenarios(scenarios);\n                    } catch (e) {\n                        throw new Error(e);\n                    }                 \n                });\n\n                function runScenarios(scenarios) {\n                    var runner = runners[mode];\n                    if (!runner) throw 'Unsupported mode: ' + mode; \n                    for (var i = 0; i < scenarios.length; i++) {\n                        runner(scenarios[i]);\n                    };       \n                };      \n\n                function runAsyncScenario(scenario) {\n                    it(scenario.title, function(done) {\n                        yadda.yadda(scenario.steps, done);\n                    });\n                };\n\n                function runSyncScenario(scenario) {\n                    it(scenario.title, function() {\n                        yadda.yadda(scenario.steps);\n                    });\n                };\n            };\n\n            Yadda.prototype.mocha = feature;\n            Yadda.prototype.jasmine = feature;\n        };\n    };\n\n    return MochaPlugin;\n})();\n},{\"fs\":19,\"../parsers/TextParser\":16}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])\n;"
  },
  {
    "path": "dist/yadda-0.4.4.js",
    "content": "require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./MochaPlugin\":17,\"./CasperPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],18:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],17:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"fs\":19,\"../parsers/TextParser\":16,\"../Yadda\":1}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])\n;"
  },
  {
    "path": "dist/yadda-0.4.5.js",
    "content": "require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":17,\"./MochaPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],18:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"fs\":19,\"../parsers/TextParser\":16,\"../Yadda\":1}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])\n;"
  },
  {
    "path": "dist/yadda-0.4.6.js",
    "content": "require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":17,\"./MochaPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":11}],18:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"fs\":19,\"../parsers/TextParser\":16,\"../Yadda\":1}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])\n;"
  },
  {
    "path": "dist/yadda-0.4.7.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":11}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":6}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":9}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./fn\":11}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":3,\"./Macro\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Environment\":4,\"./RegularExpression\":9,\"./fn\":11}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":4,\"./Interpreter\":5,\"./fn\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Dictionary\":3,\"./Interpreter\":5,\"./Library\":7,\"./Yadda\":10,\"./localisation/index\":15,\"./parsers/index\":17,\"./plugins/index\":20}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":7}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":7,\"../localisation\":15}],15:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":13,\"./Pirate\":14}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],17:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],18:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"../Yadda\":10,\"../parsers/TextParser\":16,\"fs\":21}],20:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":18,\"./MochaPlugin\":19}],21:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.5.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":11}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":6}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":9}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./fn\":11}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":3,\"./Macro\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Environment\":4,\"./RegularExpression\":9,\"./fn\":11}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.5.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":4,\"./Interpreter\":5,\"./fn\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Dictionary\":3,\"./Interpreter\":5,\"./Library\":7,\"./Yadda\":10,\"./localisation/index\":15,\"./parsers/index\":17,\"./plugins/index\":20}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":7}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":7,\"../localisation\":15}],15:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":13,\"./Pirate\":14}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return {title: current_feature, scenarios: scenarios};\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],17:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],18:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var feature = parser.parse(text);\n                runScenarios(feature.scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"../Yadda\":10,\"../parsers/TextParser\":16,\"fs\":21}],20:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":18,\"./MochaPlugin\":19}],21:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.5.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n\tvar event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n    \tif (arguments.length == 1) return this.send(event_name, {});\n    \tif (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);    \t\n        notify_handlers(event_name, event_data);\n    \tnext && next();        \n    \treturn this;\n    };\n\n \tthis.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n \t};\n\n \tvar notify_handlers = function(event_name, event_data) {\n\t\tfind_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n \t};\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    }; \t\n};\n\nfunction instance() {\n\treturn event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: ctx });        \n        var iterator = make_step_iterator(ctx, next);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    var make_step_iterator = function(ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, ctx, next) {\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n        _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":3,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, next) {   \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: ctx, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, env.ctx, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Environment\":4,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    this.interpret = this.yadda;\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.5.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":4,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Dictionary\":3,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return {title: current_feature, scenarios: scenarios};\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var feature = parser.parse(text);\n                runScenarios(feature.scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.5.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n\tvar event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n    \tif (arguments.length == 1) return this.send(event_name, {});\n    \tif (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);    \t\n        notify_handlers(event_name, event_data);\n    \tnext && next();        \n    \treturn this;\n    };\n\n \tthis.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n \t};\n\n \tvar notify_handlers = function(event_name, event_data) {\n\t\tfind_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n \t};\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    }; \t\n};\n\nfunction instance() {\n\treturn event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: ctx });        \n        var iterator = make_step_iterator(ctx, next);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    var make_step_iterator = function(ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, ctx, next) {\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n        _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":3,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, next) {   \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: ctx, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, env.ctx, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Environment\":4,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    this.interpret = this.yadda;\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.5.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":4,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Dictionary\":3,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\tvar annotations;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n\t\tannotations = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return {title: current_feature, scenarios: scenarios, annotations: annotations};\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n\t\tif (match = ANNOTATION_REGEX.exec(line)) {\n\t\t\tannotations[match[1]] = match[2];\n\t\t} else if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var feature = parser.parse(text);\n                runScenarios(feature.scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.6.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context});        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        current_scenario = { steps: [] };\n        current_feature = null;\n\t\tannotations = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        var result = {title: current_feature, scenarios: scenarios, annotations: annotations};\n        return next && next(result) || result;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n\t\tif (match = ANNOTATION_REGEX.exec(line)) {\n\t\t\tannotations[match[1]] = match[2];\n\t\t} else if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            describe(feature.title || filename, function() {         \n                next(feature);\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.6.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]'); \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        current_scenario = { steps: [] };\n        current_feature = null;\n\t\tannotations = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        var result = {title: current_feature, scenarios: scenarios, annotations: annotations};\n        return next && next(result) || result;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n\t\tif (match = ANNOTATION_REGEX.exec(line)) {\n\t\t\tannotations[match[1]] = match[2];\n\t\t} else if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature) throw new Error(\"You can only specify a single feature\");\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            describe(feature.title || filename, function() {         \n                next(feature);\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.6.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]'); \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/; \n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);    \n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");        \n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};        \n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() { \n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) { \n                next(scenario, done) \n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() { \n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.6.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]'); \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":19,\"./plugins/index\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/; \n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);    \n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");        \n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};        \n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":18}],20:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],21:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() { \n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) { \n                next(scenario, done) \n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() { \n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":18,\"fs\":23}],22:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":20,\"./MochaPlugin\":21}],23:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.6.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]'); \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":19,\"./plugins/index\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/; \n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);    \n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");        \n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};        \n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":18}],20:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],21:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() { \n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) { \n                next(scenario, done) \n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() { \n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":18,\"fs\":23}],22:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":20,\"./MochaPlugin\":21}],23:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.6.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":19,\"./plugins/index\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/; \n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);    \n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");        \n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};        \n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":18}],20:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],21:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() { \n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) { \n                next(scenario, done) \n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() { \n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":18,\"fs\":23}],22:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":20,\"./MochaPlugin\":21}],23:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.7.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.7.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":20,\"./plugins/index\":23}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar FeatureParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/;\n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};\n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],20:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":18,\"./StepParser\":19}],21:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],22:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new FeatureParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/FeatureParser\":18,\"fs\":24}],23:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":21,\"./MochaPlugin\":22}],24:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.7.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.7.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":20,\"./plugins/index\":23}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n\nvar Pirate = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar FeatureParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/;\n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};\n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],20:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":18,\"./StepParser\":19}],21:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],22:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new FeatureParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/FeatureParser\":18,\"fs\":24}],23:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":21,\"./MochaPlugin\":22}],24:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.7.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.7.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":20,\"./plugins/index\":23}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n\nvar Pirate = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar FeatureParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var COMMENT_REGEX = /^\\s*#/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/;\n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = COMMENT_REGEX.test(line)) return;\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};\n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],20:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":18,\"./StepParser\":19}],21:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],22:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new FeatureParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/FeatureParser\":18,\"fs\":24}],23:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":21,\"./MochaPlugin\":22}],24:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.8.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.7.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":18,\"./parsers/index\":21,\"./plugins/index\":24}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)'\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(['given', 'when', 'then']).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":8}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+'\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n}\n},{\"./English\":15,\"./Pirate\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n    console.log(language.localise('scenario'));\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var STEP_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var COMMENT_REGEX = new RegExp('^\\\\s*#', 'i');\n    var NON_BLANK_REGEX = new RegExp('[^\\\\s]', 'i');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$', 'i');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$', 'i');\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = COMMENT_REGEX.test(line)) return;\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};\n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":15}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],21:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":19,\"./StepParser\":20}],22:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],23:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../localisation/English\":15,\"../parsers/FeatureParser\":19,\"fs\":25}],24:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":22,\"./MochaPlugin\":23}],25:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.8.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":18,\"./parsers/index\":21,\"./plugins/index\":24}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)'\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(['given', 'when', 'then']).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":8}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+'\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":15,\"./Language\":16,\"./Pirate\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":15}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],21:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":19,\"./StepParser\":20}],22:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],23:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n            _describe(feature.title[0] || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title[0], function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title[0], function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../localisation/English\":15,\"../parsers/FeatureParser\":19,\"fs\":25}],24:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":22,\"./MochaPlugin\":23}],25:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.8.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":19,\"./parsers/index\":22,\"./plugins/index\":25}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)'\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(['given', 'when', 'then']).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":8}],17:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)'\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+'\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":16}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":15,\"./Language\":16,\"./Norwegian\":17,\"./Pirate\":18}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":15}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],22:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":20,\"./StepParser\":21}],23:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],24:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../localisation/English\":15,\"../parsers/FeatureParser\":20,\"fs\":26}],25:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":23,\"./MochaPlugin\":24}],26:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.8.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)'\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(['given', 'when', 'then']).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)'\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+'\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"W+dgdo\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":36,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":36,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\nvar Buffer=require(\"__browserify_Buffer\").Buffer;// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg instanceof Buffer;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"__browserify_Buffer\":35,\"_shims\":31}],35:[function(require,module,exports){\nrequire=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\nexports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {\n  var e, m,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      nBits = -7,\n      i = isBE ? 0 : (nBytes - 1),\n      d = isBE ? 1 : -1,\n      s = buffer[offset + i];\n\n  i += d;\n\n  e = s & ((1 << (-nBits)) - 1);\n  s >>= (-nBits);\n  nBits += eLen;\n  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  m = e & ((1 << (-nBits)) - 1);\n  e >>= (-nBits);\n  nBits += mLen;\n  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  if (e === 0) {\n    e = 1 - eBias;\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity);\n  } else {\n    m = m + Math.pow(2, mLen);\n    e = e - eBias;\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);\n};\n\nexports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {\n  var e, m, c,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),\n      i = isBE ? (nBytes - 1) : 0,\n      d = isBE ? -1 : 1,\n      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;\n\n  value = Math.abs(value);\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0;\n    e = eMax;\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2);\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--;\n      c *= 2;\n    }\n    if (e + eBias >= 1) {\n      value += rt / c;\n    } else {\n      value += rt * Math.pow(2, 1 - eBias);\n    }\n    if (value * c >= 2) {\n      e++;\n      c /= 2;\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0;\n      e = eMax;\n    } else if (e + eBias >= 1) {\n      m = (value * c - 1) * Math.pow(2, mLen);\n      e = e + eBias;\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);\n      e = 0;\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);\n\n  e = (e << mLen) | m;\n  eLen += mLen;\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);\n\n  buffer[offset + i - d] |= s * 128;\n};\n\n},{}],\"q9TxCC\":[function(require,module,exports){\nvar assert;\nexports.Buffer = Buffer;\nexports.SlowBuffer = Buffer;\nBuffer.poolSize = 8192;\nexports.INSPECT_MAX_BYTES = 50;\n\nfunction stringtrim(str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n}\n\nfunction Buffer(subject, encoding, offset) {\n  if(!assert) assert= require('assert');\n  if (!(this instanceof Buffer)) {\n    return new Buffer(subject, encoding, offset);\n  }\n  this.parent = this;\n  this.offset = 0;\n\n  // Work-around: node's base64 implementation\n  // allows for non-padded strings while base64-js\n  // does not..\n  if (encoding == \"base64\" && typeof subject == \"string\") {\n    subject = stringtrim(subject);\n    while (subject.length % 4 != 0) {\n      subject = subject + \"=\"; \n    }\n  }\n\n  var type;\n\n  // Are we slicing?\n  if (typeof offset === 'number') {\n    this.length = coerce(encoding);\n    // slicing works, with limitations (no parent tracking/update)\n    // check https://github.com/toots/buffer-browserify/issues/19\n    for (var i = 0; i < this.length; i++) {\n        this[i] = subject.get(i+offset);\n    }\n  } else {\n    // Find the length\n    switch (type = typeof subject) {\n      case 'number':\n        this.length = coerce(subject);\n        break;\n\n      case 'string':\n        this.length = Buffer.byteLength(subject, encoding);\n        break;\n\n      case 'object': // Assume object is an array\n        this.length = coerce(subject.length);\n        break;\n\n      default:\n        throw new Error('First argument needs to be a number, ' +\n                        'array or string.');\n    }\n\n    // Treat array-ish objects as a byte array.\n    if (isArrayIsh(subject)) {\n      for (var i = 0; i < this.length; i++) {\n        if (subject instanceof Buffer) {\n          this[i] = subject.readUInt8(i);\n        }\n        else {\n          this[i] = subject[i];\n        }\n      }\n    } else if (type == 'string') {\n      // We are a string\n      this.length = this.write(subject, 0, encoding);\n    } else if (type === 'number') {\n      for (var i = 0; i < this.length; i++) {\n        this[i] = 0;\n      }\n    }\n  }\n}\n\nBuffer.prototype.get = function get(i) {\n  if (i < 0 || i >= this.length) throw new Error('oob');\n  return this[i];\n};\n\nBuffer.prototype.set = function set(i, v) {\n  if (i < 0 || i >= this.length) throw new Error('oob');\n  return this[i] = v;\n};\n\nBuffer.byteLength = function (str, encoding) {\n  switch (encoding || \"utf8\") {\n    case 'hex':\n      return str.length / 2;\n\n    case 'utf8':\n    case 'utf-8':\n      return utf8ToBytes(str).length;\n\n    case 'ascii':\n    case 'binary':\n      return str.length;\n\n    case 'base64':\n      return base64ToBytes(str).length;\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\nBuffer.prototype.utf8Write = function (string, offset, length) {\n  var bytes, pos;\n  return Buffer._charsWritten =  blitBuffer(utf8ToBytes(string), this, offset, length);\n};\n\nBuffer.prototype.asciiWrite = function (string, offset, length) {\n  var bytes, pos;\n  return Buffer._charsWritten =  blitBuffer(asciiToBytes(string), this, offset, length);\n};\n\nBuffer.prototype.binaryWrite = Buffer.prototype.asciiWrite;\n\nBuffer.prototype.base64Write = function (string, offset, length) {\n  var bytes, pos;\n  return Buffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);\n};\n\nBuffer.prototype.base64Slice = function (start, end) {\n  var bytes = Array.prototype.slice.apply(this, arguments)\n  return require(\"base64-js\").fromByteArray(bytes);\n};\n\nBuffer.prototype.utf8Slice = function () {\n  var bytes = Array.prototype.slice.apply(this, arguments);\n  var res = \"\";\n  var tmp = \"\";\n  var i = 0;\n  while (i < bytes.length) {\n    if (bytes[i] <= 0x7F) {\n      res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);\n      tmp = \"\";\n    } else\n      tmp += \"%\" + bytes[i].toString(16);\n\n    i++;\n  }\n\n  return res + decodeUtf8Char(tmp);\n}\n\nBuffer.prototype.asciiSlice = function () {\n  var bytes = Array.prototype.slice.apply(this, arguments);\n  var ret = \"\";\n  for (var i = 0; i < bytes.length; i++)\n    ret += String.fromCharCode(bytes[i]);\n  return ret;\n}\n\nBuffer.prototype.binarySlice = Buffer.prototype.asciiSlice;\n\nBuffer.prototype.inspect = function() {\n  var out = [],\n      len = this.length;\n  for (var i = 0; i < len; i++) {\n    out[i] = toHex(this[i]);\n    if (i == exports.INSPECT_MAX_BYTES) {\n      out[i + 1] = '...';\n      break;\n    }\n  }\n  return '<Buffer ' + out.join(' ') + '>';\n};\n\n\nBuffer.prototype.hexSlice = function(start, end) {\n  var len = this.length;\n\n  if (!start || start < 0) start = 0;\n  if (!end || end < 0 || end > len) end = len;\n\n  var out = '';\n  for (var i = start; i < end; i++) {\n    out += toHex(this[i]);\n  }\n  return out;\n};\n\n\nBuffer.prototype.toString = function(encoding, start, end) {\n  encoding = String(encoding || 'utf8').toLowerCase();\n  start = +start || 0;\n  if (typeof end == 'undefined') end = this.length;\n\n  // Fastpath empty strings\n  if (+end == start) {\n    return '';\n  }\n\n  switch (encoding) {\n    case 'hex':\n      return this.hexSlice(start, end);\n\n    case 'utf8':\n    case 'utf-8':\n      return this.utf8Slice(start, end);\n\n    case 'ascii':\n      return this.asciiSlice(start, end);\n\n    case 'binary':\n      return this.binarySlice(start, end);\n\n    case 'base64':\n      return this.base64Slice(start, end);\n\n    case 'ucs2':\n    case 'ucs-2':\n      return this.ucs2Slice(start, end);\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\n\nBuffer.prototype.hexWrite = function(string, offset, length) {\n  offset = +offset || 0;\n  var remaining = this.length - offset;\n  if (!length) {\n    length = remaining;\n  } else {\n    length = +length;\n    if (length > remaining) {\n      length = remaining;\n    }\n  }\n\n  // must be an even number of digits\n  var strLen = string.length;\n  if (strLen % 2) {\n    throw new Error('Invalid hex string');\n  }\n  if (length > strLen / 2) {\n    length = strLen / 2;\n  }\n  for (var i = 0; i < length; i++) {\n    var byte = parseInt(string.substr(i * 2, 2), 16);\n    if (isNaN(byte)) throw new Error('Invalid hex string');\n    this[offset + i] = byte;\n  }\n  Buffer._charsWritten = i * 2;\n  return i;\n};\n\n\nBuffer.prototype.write = function(string, offset, length, encoding) {\n  // Support both (string, offset, length, encoding)\n  // and the legacy (string, encoding, offset, length)\n  if (isFinite(offset)) {\n    if (!isFinite(length)) {\n      encoding = length;\n      length = undefined;\n    }\n  } else {  // legacy\n    var swap = encoding;\n    encoding = offset;\n    offset = length;\n    length = swap;\n  }\n\n  offset = +offset || 0;\n  var remaining = this.length - offset;\n  if (!length) {\n    length = remaining;\n  } else {\n    length = +length;\n    if (length > remaining) {\n      length = remaining;\n    }\n  }\n  encoding = String(encoding || 'utf8').toLowerCase();\n\n  switch (encoding) {\n    case 'hex':\n      return this.hexWrite(string, offset, length);\n\n    case 'utf8':\n    case 'utf-8':\n      return this.utf8Write(string, offset, length);\n\n    case 'ascii':\n      return this.asciiWrite(string, offset, length);\n\n    case 'binary':\n      return this.binaryWrite(string, offset, length);\n\n    case 'base64':\n      return this.base64Write(string, offset, length);\n\n    case 'ucs2':\n    case 'ucs-2':\n      return this.ucs2Write(string, offset, length);\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\n// slice(start, end)\nfunction clamp(index, len, defaultValue) {\n  if (typeof index !== 'number') return defaultValue;\n  index = ~~index;  // Coerce to integer.\n  if (index >= len) return len;\n  if (index >= 0) return index;\n  index += len;\n  if (index >= 0) return index;\n  return 0;\n}\n\nBuffer.prototype.slice = function(start, end) {\n  var len = this.length;\n  start = clamp(start, len, 0);\n  end = clamp(end, len, len);\n  return new Buffer(this, end - start, +start);\n};\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function(target, target_start, start, end) {\n  var source = this;\n  start || (start = 0);\n  if (end === undefined || isNaN(end)) {\n    end = this.length;\n  }\n  target_start || (target_start = 0);\n\n  if (end < start) throw new Error('sourceEnd < sourceStart');\n\n  // Copy 0 bytes; we're done\n  if (end === start) return 0;\n  if (target.length == 0 || source.length == 0) return 0;\n\n  if (target_start < 0 || target_start >= target.length) {\n    throw new Error('targetStart out of bounds');\n  }\n\n  if (start < 0 || start >= source.length) {\n    throw new Error('sourceStart out of bounds');\n  }\n\n  if (end < 0 || end > source.length) {\n    throw new Error('sourceEnd out of bounds');\n  }\n\n  // Are we oob?\n  if (end > this.length) {\n    end = this.length;\n  }\n\n  if (target.length - target_start < end - start) {\n    end = target.length - target_start + start;\n  }\n\n  var temp = [];\n  for (var i=start; i<end; i++) {\n    assert.ok(typeof this[i] !== 'undefined', \"copying undefined buffer bytes!\");\n    temp.push(this[i]);\n  }\n\n  for (var i=target_start; i<target_start+temp.length; i++) {\n    target[i] = temp[i-target_start];\n  }\n};\n\n// fill(value, start=0, end=buffer.length)\nBuffer.prototype.fill = function fill(value, start, end) {\n  value || (value = 0);\n  start || (start = 0);\n  end || (end = this.length);\n\n  if (typeof value === 'string') {\n    value = value.charCodeAt(0);\n  }\n  if (!(typeof value === 'number') || isNaN(value)) {\n    throw new Error('value is not a number');\n  }\n\n  if (end < start) throw new Error('end < start');\n\n  // Fill 0 bytes; we're done\n  if (end === start) return 0;\n  if (this.length == 0) return 0;\n\n  if (start < 0 || start >= this.length) {\n    throw new Error('start out of bounds');\n  }\n\n  if (end < 0 || end > this.length) {\n    throw new Error('end out of bounds');\n  }\n\n  for (var i = start; i < end; i++) {\n    this[i] = value;\n  }\n}\n\n// Static methods\nBuffer.isBuffer = function isBuffer(b) {\n  return b instanceof Buffer || b instanceof Buffer;\n};\n\nBuffer.concat = function (list, totalLength) {\n  if (!isArray(list)) {\n    throw new Error(\"Usage: Buffer.concat(list, [totalLength])\\n \\\n      list should be an Array.\");\n  }\n\n  if (list.length === 0) {\n    return new Buffer(0);\n  } else if (list.length === 1) {\n    return list[0];\n  }\n\n  if (typeof totalLength !== 'number') {\n    totalLength = 0;\n    for (var i = 0; i < list.length; i++) {\n      var buf = list[i];\n      totalLength += buf.length;\n    }\n  }\n\n  var buffer = new Buffer(totalLength);\n  var pos = 0;\n  for (var i = 0; i < list.length; i++) {\n    var buf = list[i];\n    buf.copy(buffer, pos);\n    pos += buf.length;\n  }\n  return buffer;\n};\n\nBuffer.isEncoding = function(encoding) {\n  switch ((encoding + '').toLowerCase()) {\n    case 'hex':\n    case 'utf8':\n    case 'utf-8':\n    case 'ascii':\n    case 'binary':\n    case 'base64':\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n    case 'raw':\n      return true;\n\n    default:\n      return false;\n  }\n};\n\n// helpers\n\nfunction coerce(length) {\n  // Coerce length to a number (possibly NaN), round up\n  // in case it's fractional (e.g. 123.456) then do a\n  // double negate to coerce a NaN to 0. Easy, right?\n  length = ~~Math.ceil(+length);\n  return length < 0 ? 0 : length;\n}\n\nfunction isArray(subject) {\n  return (Array.isArray ||\n    function(subject){\n      return {}.toString.apply(subject) == '[object Array]'\n    })\n    (subject)\n}\n\nfunction isArrayIsh(subject) {\n  return isArray(subject) || Buffer.isBuffer(subject) ||\n         subject && typeof subject === 'object' &&\n         typeof subject.length === 'number';\n}\n\nfunction toHex(n) {\n  if (n < 16) return '0' + n.toString(16);\n  return n.toString(16);\n}\n\nfunction utf8ToBytes(str) {\n  var byteArray = [];\n  for (var i = 0; i < str.length; i++)\n    if (str.charCodeAt(i) <= 0x7F)\n      byteArray.push(str.charCodeAt(i));\n    else {\n      var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');\n      for (var j = 0; j < h.length; j++)\n        byteArray.push(parseInt(h[j], 16));\n    }\n\n  return byteArray;\n}\n\nfunction asciiToBytes(str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++ )\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push( str.charCodeAt(i) & 0xFF );\n\n  return byteArray;\n}\n\nfunction base64ToBytes(str) {\n  return require(\"base64-js\").toByteArray(str);\n}\n\nfunction blitBuffer(src, dst, offset, length) {\n  var pos, i = 0;\n  while (i < length) {\n    if ((i+offset >= dst.length) || (i >= src.length))\n      break;\n\n    dst[i + offset] = src[i];\n    i++;\n  }\n  return i;\n}\n\nfunction decodeUtf8Char(str) {\n  try {\n    return decodeURIComponent(str);\n  } catch (err) {\n    return String.fromCharCode(0xFFFD); // UTF 8 invalid char\n  }\n}\n\n// read/write bit-twiddling\n\nBuffer.prototype.readUInt8 = function(offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return;\n\n  return buffer[offset];\n};\n\nfunction readUInt16(buffer, offset, isBigEndian, noAssert) {\n  var val = 0;\n\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return 0;\n\n  if (isBigEndian) {\n    val = buffer[offset] << 8;\n    if (offset + 1 < buffer.length) {\n      val |= buffer[offset + 1];\n    }\n  } else {\n    val = buffer[offset];\n    if (offset + 1 < buffer.length) {\n      val |= buffer[offset + 1] << 8;\n    }\n  }\n\n  return val;\n}\n\nBuffer.prototype.readUInt16LE = function(offset, noAssert) {\n  return readUInt16(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readUInt16BE = function(offset, noAssert) {\n  return readUInt16(this, offset, true, noAssert);\n};\n\nfunction readUInt32(buffer, offset, isBigEndian, noAssert) {\n  var val = 0;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return 0;\n\n  if (isBigEndian) {\n    if (offset + 1 < buffer.length)\n      val = buffer[offset + 1] << 16;\n    if (offset + 2 < buffer.length)\n      val |= buffer[offset + 2] << 8;\n    if (offset + 3 < buffer.length)\n      val |= buffer[offset + 3];\n    val = val + (buffer[offset] << 24 >>> 0);\n  } else {\n    if (offset + 2 < buffer.length)\n      val = buffer[offset + 2] << 16;\n    if (offset + 1 < buffer.length)\n      val |= buffer[offset + 1] << 8;\n    val |= buffer[offset];\n    if (offset + 3 < buffer.length)\n      val = val + (buffer[offset + 3] << 24 >>> 0);\n  }\n\n  return val;\n}\n\nBuffer.prototype.readUInt32LE = function(offset, noAssert) {\n  return readUInt32(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readUInt32BE = function(offset, noAssert) {\n  return readUInt32(this, offset, true, noAssert);\n};\n\n\n/*\n * Signed integer types, yay team! A reminder on how two's complement actually\n * works. The first bit is the signed bit, i.e. tells us whether or not the\n * number should be positive or negative. If the two's complement value is\n * positive, then we're done, as it's equivalent to the unsigned representation.\n *\n * Now if the number is positive, you're pretty much done, you can just leverage\n * the unsigned translations and return those. Unfortunately, negative numbers\n * aren't quite that straightforward.\n *\n * At first glance, one might be inclined to use the traditional formula to\n * translate binary numbers between the positive and negative values in two's\n * complement. (Though it doesn't quite work for the most negative value)\n * Mainly:\n *  - invert all the bits\n *  - add one to the result\n *\n * Of course, this doesn't quite work in Javascript. Take for example the value\n * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of\n * course, Javascript will do the following:\n *\n * > ~0xff80\n * -65409\n *\n * Whoh there, Javascript, that's not quite right. But wait, according to\n * Javascript that's perfectly correct. When Javascript ends up seeing the\n * constant 0xff80, it has no notion that it is actually a signed number. It\n * assumes that we've input the unsigned value 0xff80. Thus, when it does the\n * binary negation, it casts it into a signed value, (positive 0xff80). Then\n * when you perform binary negation on that, it turns it into a negative number.\n *\n * Instead, we're going to have to use the following general formula, that works\n * in a rather Javascript friendly way. I'm glad we don't support this kind of\n * weird numbering scheme in the kernel.\n *\n * (BIT-MAX - (unsigned)val + 1) * -1\n *\n * The astute observer, may think that this doesn't make sense for 8-bit numbers\n * (really it isn't necessary for them). However, when you get 16-bit numbers,\n * you do. Let's go back to our prior example and see how this will look:\n *\n * (0xffff - 0xff80 + 1) * -1\n * (0x007f + 1) * -1\n * (0x0080) * -1\n */\nBuffer.prototype.readInt8 = function(offset, noAssert) {\n  var buffer = this;\n  var neg;\n\n  if (!noAssert) {\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return;\n\n  neg = buffer[offset] & 0x80;\n  if (!neg) {\n    return (buffer[offset]);\n  }\n\n  return ((0xff - buffer[offset] + 1) * -1);\n};\n\nfunction readInt16(buffer, offset, isBigEndian, noAssert) {\n  var neg, val;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  val = readUInt16(buffer, offset, isBigEndian, noAssert);\n  neg = val & 0x8000;\n  if (!neg) {\n    return val;\n  }\n\n  return (0xffff - val + 1) * -1;\n}\n\nBuffer.prototype.readInt16LE = function(offset, noAssert) {\n  return readInt16(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readInt16BE = function(offset, noAssert) {\n  return readInt16(this, offset, true, noAssert);\n};\n\nfunction readInt32(buffer, offset, isBigEndian, noAssert) {\n  var neg, val;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  val = readUInt32(buffer, offset, isBigEndian, noAssert);\n  neg = val & 0x80000000;\n  if (!neg) {\n    return (val);\n  }\n\n  return (0xffffffff - val + 1) * -1;\n}\n\nBuffer.prototype.readInt32LE = function(offset, noAssert) {\n  return readInt32(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readInt32BE = function(offset, noAssert) {\n  return readInt32(this, offset, true, noAssert);\n};\n\nfunction readFloat(buffer, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,\n      23, 4);\n}\n\nBuffer.prototype.readFloatLE = function(offset, noAssert) {\n  return readFloat(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readFloatBE = function(offset, noAssert) {\n  return readFloat(this, offset, true, noAssert);\n};\n\nfunction readDouble(buffer, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset + 7 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,\n      52, 8);\n}\n\nBuffer.prototype.readDoubleLE = function(offset, noAssert) {\n  return readDouble(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readDoubleBE = function(offset, noAssert) {\n  return readDouble(this, offset, true, noAssert);\n};\n\n\n/*\n * We have to make sure that the value is a valid integer. This means that it is\n * non-negative. It has no fractional component and that it does not exceed the\n * maximum allowed value.\n *\n *      value           The number to check for validity\n *\n *      max             The maximum value\n */\nfunction verifuint(value, max) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value >= 0,\n      'specified a negative value for writing an unsigned value');\n\n  assert.ok(value <= max, 'value is larger than maximum value for type');\n\n  assert.ok(Math.floor(value) === value, 'value has a fractional component');\n}\n\nBuffer.prototype.writeUInt8 = function(value, offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xff);\n  }\n\n  if (offset < buffer.length) {\n    buffer[offset] = value;\n  }\n};\n\nfunction writeUInt16(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xffff);\n  }\n\n  for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {\n    buffer[offset + i] =\n        (value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>\n            (isBigEndian ? 1 - i : i) * 8;\n  }\n\n}\n\nBuffer.prototype.writeUInt16LE = function(value, offset, noAssert) {\n  writeUInt16(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeUInt16BE = function(value, offset, noAssert) {\n  writeUInt16(this, value, offset, true, noAssert);\n};\n\nfunction writeUInt32(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xffffffff);\n  }\n\n  for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {\n    buffer[offset + i] =\n        (value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;\n  }\n}\n\nBuffer.prototype.writeUInt32LE = function(value, offset, noAssert) {\n  writeUInt32(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeUInt32BE = function(value, offset, noAssert) {\n  writeUInt32(this, value, offset, true, noAssert);\n};\n\n\n/*\n * We now move onto our friends in the signed number category. Unlike unsigned\n * numbers, we're going to have to worry a bit more about how we put values into\n * arrays. Since we are only worrying about signed 32-bit values, we're in\n * slightly better shape. Unfortunately, we really can't do our favorite binary\n * & in this system. It really seems to do the wrong thing. For example:\n *\n * > -32 & 0xff\n * 224\n *\n * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of\n * this aren't treated as a signed number. Ultimately a bad thing.\n *\n * What we're going to want to do is basically create the unsigned equivalent of\n * our representation and pass that off to the wuint* functions. To do that\n * we're going to do the following:\n *\n *  - if the value is positive\n *      we can pass it directly off to the equivalent wuint\n *  - if the value is negative\n *      we do the following computation:\n *         mb + val + 1, where\n *         mb   is the maximum unsigned value in that byte size\n *         val  is the Javascript negative integer\n *\n *\n * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If\n * you do out the computations:\n *\n * 0xffff - 128 + 1\n * 0xffff - 127\n * 0xff80\n *\n * You can then encode this value as the signed version. This is really rather\n * hacky, but it should work and get the job done which is our goal here.\n */\n\n/*\n * A series of checks to make sure we actually have a signed 32-bit number\n */\nfunction verifsint(value, max, min) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value <= max, 'value larger than maximum allowed value');\n\n  assert.ok(value >= min, 'value smaller than minimum allowed value');\n\n  assert.ok(Math.floor(value) === value, 'value has a fractional component');\n}\n\nfunction verifIEEE754(value, max, min) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value <= max, 'value larger than maximum allowed value');\n\n  assert.ok(value >= min, 'value smaller than minimum allowed value');\n}\n\nBuffer.prototype.writeInt8 = function(value, offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7f, -0x80);\n  }\n\n  if (value >= 0) {\n    buffer.writeUInt8(value, offset, noAssert);\n  } else {\n    buffer.writeUInt8(0xff + value + 1, offset, noAssert);\n  }\n};\n\nfunction writeInt16(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7fff, -0x8000);\n  }\n\n  if (value >= 0) {\n    writeUInt16(buffer, value, offset, isBigEndian, noAssert);\n  } else {\n    writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);\n  }\n}\n\nBuffer.prototype.writeInt16LE = function(value, offset, noAssert) {\n  writeInt16(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeInt16BE = function(value, offset, noAssert) {\n  writeInt16(this, value, offset, true, noAssert);\n};\n\nfunction writeInt32(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7fffffff, -0x80000000);\n  }\n\n  if (value >= 0) {\n    writeUInt32(buffer, value, offset, isBigEndian, noAssert);\n  } else {\n    writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);\n  }\n}\n\nBuffer.prototype.writeInt32LE = function(value, offset, noAssert) {\n  writeInt32(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeInt32BE = function(value, offset, noAssert) {\n  writeInt32(this, value, offset, true, noAssert);\n};\n\nfunction writeFloat(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);\n  }\n\n  require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,\n      23, 4);\n}\n\nBuffer.prototype.writeFloatLE = function(value, offset, noAssert) {\n  writeFloat(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeFloatBE = function(value, offset, noAssert) {\n  writeFloat(this, value, offset, true, noAssert);\n};\n\nfunction writeDouble(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 7 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);\n  }\n\n  require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,\n      52, 8);\n}\n\nBuffer.prototype.writeDoubleLE = function(value, offset, noAssert) {\n  writeDouble(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeDoubleBE = function(value, offset, noAssert) {\n  writeDouble(this, value, offset, true, noAssert);\n};\n\n},{\"./buffer_ieee754\":1,\"assert\":6,\"base64-js\":4}],\"buffer-browserify\":[function(require,module,exports){\nmodule.exports=require('q9TxCC');\n},{}],4:[function(require,module,exports){\n(function (exports) {\n\t'use strict';\n\n\tvar lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n\tfunction b64ToByteArray(b64) {\n\t\tvar i, j, l, tmp, placeHolders, arr;\n\t\n\t\tif (b64.length % 4 > 0) {\n\t\t\tthrow 'Invalid string. Length must be a multiple of 4';\n\t\t}\n\n\t\t// the number of equal signs (place holders)\n\t\t// if there are two placeholders, than the two characters before it\n\t\t// represent one byte\n\t\t// if there is only one, then the three characters before it represent 2 bytes\n\t\t// this is just a cheap hack to not do indexOf twice\n\t\tplaceHolders = b64.indexOf('=');\n\t\tplaceHolders = placeHolders > 0 ? b64.length - placeHolders : 0;\n\n\t\t// base64 is 4/3 + up to two characters of the original data\n\t\tarr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);\n\n\t\t// if there are placeholders, only get up to the last complete 4 chars\n\t\tl = placeHolders > 0 ? b64.length - 4 : b64.length;\n\n\t\tfor (i = 0, j = 0; i < l; i += 4, j += 3) {\n\t\t\ttmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);\n\t\t\tarr.push((tmp & 0xFF0000) >> 16);\n\t\t\tarr.push((tmp & 0xFF00) >> 8);\n\t\t\tarr.push(tmp & 0xFF);\n\t\t}\n\n\t\tif (placeHolders === 2) {\n\t\t\ttmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);\n\t\t\tarr.push(tmp & 0xFF);\n\t\t} else if (placeHolders === 1) {\n\t\t\ttmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);\n\t\t\tarr.push((tmp >> 8) & 0xFF);\n\t\t\tarr.push(tmp & 0xFF);\n\t\t}\n\n\t\treturn arr;\n\t}\n\n\tfunction uint8ToBase64(uint8) {\n\t\tvar i,\n\t\t\textraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes\n\t\t\toutput = \"\",\n\t\t\ttemp, length;\n\n\t\tfunction tripletToBase64 (num) {\n\t\t\treturn lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];\n\t\t};\n\n\t\t// go through the array every three bytes, we'll deal with trailing stuff later\n\t\tfor (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {\n\t\t\ttemp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);\n\t\t\toutput += tripletToBase64(temp);\n\t\t}\n\n\t\t// pad the end with zeros, but make sure to not forget the extra bytes\n\t\tswitch (extraBytes) {\n\t\t\tcase 1:\n\t\t\t\ttemp = uint8[uint8.length - 1];\n\t\t\t\toutput += lookup[temp >> 2];\n\t\t\t\toutput += lookup[(temp << 4) & 0x3F];\n\t\t\t\toutput += '==';\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\ttemp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);\n\t\t\t\toutput += lookup[temp >> 10];\n\t\t\t\toutput += lookup[(temp >> 4) & 0x3F];\n\t\t\t\toutput += lookup[(temp << 2) & 0x3F];\n\t\t\t\toutput += '=';\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn output;\n\t}\n\n\tmodule.exports.toByteArray = b64ToByteArray;\n\tmodule.exports.fromByteArray = uint8ToBase64;\n}());\n\n},{}],5:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],6:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// UTILITY\nvar util = require('util');\nvar shims = require('_shims');\nvar pSlice = Array.prototype.slice;\n\n// 1. The assert module provides functions that throw\n// AssertionError's when particular conditions are not met. The\n// assert module must conform to the following interface.\n\nvar assert = module.exports = ok;\n\n// 2. The AssertionError is defined in assert.\n// new assert.AssertionError({ message: message,\n//                             actual: actual,\n//                             expected: expected })\n\nassert.AssertionError = function AssertionError(options) {\n  this.name = 'AssertionError';\n  this.actual = options.actual;\n  this.expected = options.expected;\n  this.operator = options.operator;\n  this.message = options.message || getMessage(this);\n};\n\n// assert.AssertionError instanceof Error\nutil.inherits(assert.AssertionError, Error);\n\nfunction replacer(key, value) {\n  if (util.isUndefined(value)) {\n    return '' + value;\n  }\n  if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {\n    return value.toString();\n  }\n  if (util.isFunction(value) || util.isRegExp(value)) {\n    return value.toString();\n  }\n  return value;\n}\n\nfunction truncate(s, n) {\n  if (util.isString(s)) {\n    return s.length < n ? s : s.slice(0, n);\n  } else {\n    return s;\n  }\n}\n\nfunction getMessage(self) {\n  return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +\n         self.operator + ' ' +\n         truncate(JSON.stringify(self.expected, replacer), 128);\n}\n\n// At present only the three keys mentioned above are used and\n// understood by the spec. Implementations or sub modules can pass\n// other keys to the AssertionError's constructor - they will be\n// ignored.\n\n// 3. All of the following functions must throw an AssertionError\n// when a corresponding condition is not met, with a message that\n// may be undefined if not provided.  All assertion methods provide\n// both the actual and expected values to the assertion error for\n// display purposes.\n\nfunction fail(actual, expected, message, operator, stackStartFunction) {\n  throw new assert.AssertionError({\n    message: message,\n    actual: actual,\n    expected: expected,\n    operator: operator,\n    stackStartFunction: stackStartFunction\n  });\n}\n\n// EXTENSION! allows for well behaved errors defined elsewhere.\nassert.fail = fail;\n\n// 4. Pure assertion tests whether a value is truthy, as determined\n// by !!guard.\n// assert.ok(guard, message_opt);\n// This statement is equivalent to assert.equal(true, !!guard,\n// message_opt);. To test strictly for the value true, use\n// assert.strictEqual(true, guard, message_opt);.\n\nfunction ok(value, message) {\n  if (!value) fail(value, true, message, '==', assert.ok);\n}\nassert.ok = ok;\n\n// 5. The equality assertion tests shallow, coercive equality with\n// ==.\n// assert.equal(actual, expected, message_opt);\n\nassert.equal = function equal(actual, expected, message) {\n  if (actual != expected) fail(actual, expected, message, '==', assert.equal);\n};\n\n// 6. The non-equality assertion tests for whether two objects are not equal\n// with != assert.notEqual(actual, expected, message_opt);\n\nassert.notEqual = function notEqual(actual, expected, message) {\n  if (actual == expected) {\n    fail(actual, expected, message, '!=', assert.notEqual);\n  }\n};\n\n// 7. The equivalence assertion tests a deep equality relation.\n// assert.deepEqual(actual, expected, message_opt);\n\nassert.deepEqual = function deepEqual(actual, expected, message) {\n  if (!_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'deepEqual', assert.deepEqual);\n  }\n};\n\nfunction _deepEqual(actual, expected) {\n  // 7.1. All identical values are equivalent, as determined by ===.\n  if (actual === expected) {\n    return true;\n\n  } else if (util.isBuffer(actual) && util.isBuffer(expected)) {\n    if (actual.length != expected.length) return false;\n\n    for (var i = 0; i < actual.length; i++) {\n      if (actual[i] !== expected[i]) return false;\n    }\n\n    return true;\n\n  // 7.2. If the expected value is a Date object, the actual value is\n  // equivalent if it is also a Date object that refers to the same time.\n  } else if (util.isDate(actual) && util.isDate(expected)) {\n    return actual.getTime() === expected.getTime();\n\n  // 7.3 If the expected value is a RegExp object, the actual value is\n  // equivalent if it is also a RegExp object with the same source and\n  // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).\n  } else if (util.isRegExp(actual) && util.isRegExp(expected)) {\n    return actual.source === expected.source &&\n           actual.global === expected.global &&\n           actual.multiline === expected.multiline &&\n           actual.lastIndex === expected.lastIndex &&\n           actual.ignoreCase === expected.ignoreCase;\n\n  // 7.4. Other pairs that do not both pass typeof value == 'object',\n  // equivalence is determined by ==.\n  } else if (!util.isObject(actual) && !util.isObject(expected)) {\n    return actual == expected;\n\n  // 7.5 For all other Object pairs, including Array objects, equivalence is\n  // determined by having the same number of owned properties (as verified\n  // with Object.prototype.hasOwnProperty.call), the same set of keys\n  // (although not necessarily the same order), equivalent values for every\n  // corresponding key, and an identical 'prototype' property. Note: this\n  // accounts for both named and indexed properties on Arrays.\n  } else {\n    return objEquiv(actual, expected);\n  }\n}\n\nfunction isArguments(object) {\n  return Object.prototype.toString.call(object) == '[object Arguments]';\n}\n\nfunction objEquiv(a, b) {\n  if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))\n    return false;\n  // an identical 'prototype' property.\n  if (a.prototype !== b.prototype) return false;\n  //~~~I've managed to break Object.keys through screwy arguments passing.\n  //   Converting to array solves the problem.\n  if (isArguments(a)) {\n    if (!isArguments(b)) {\n      return false;\n    }\n    a = pSlice.call(a);\n    b = pSlice.call(b);\n    return _deepEqual(a, b);\n  }\n  try {\n    var ka = shims.keys(a),\n        kb = shims.keys(b),\n        key, i;\n  } catch (e) {//happens when one is a string literal and the other isn't\n    return false;\n  }\n  // having the same number of owned properties (keys incorporates\n  // hasOwnProperty)\n  if (ka.length != kb.length)\n    return false;\n  //the same set of keys (although not necessarily the same order),\n  ka.sort();\n  kb.sort();\n  //~~~cheap key test\n  for (i = ka.length - 1; i >= 0; i--) {\n    if (ka[i] != kb[i])\n      return false;\n  }\n  //equivalent values for every corresponding key, and\n  //~~~possibly expensive deep test\n  for (i = ka.length - 1; i >= 0; i--) {\n    key = ka[i];\n    if (!_deepEqual(a[key], b[key])) return false;\n  }\n  return true;\n}\n\n// 8. The non-equivalence assertion tests for any deep inequality.\n// assert.notDeepEqual(actual, expected, message_opt);\n\nassert.notDeepEqual = function notDeepEqual(actual, expected, message) {\n  if (_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);\n  }\n};\n\n// 9. The strict equality assertion tests strict equality, as determined by ===.\n// assert.strictEqual(actual, expected, message_opt);\n\nassert.strictEqual = function strictEqual(actual, expected, message) {\n  if (actual !== expected) {\n    fail(actual, expected, message, '===', assert.strictEqual);\n  }\n};\n\n// 10. The strict non-equality assertion tests for strict inequality, as\n// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);\n\nassert.notStrictEqual = function notStrictEqual(actual, expected, message) {\n  if (actual === expected) {\n    fail(actual, expected, message, '!==', assert.notStrictEqual);\n  }\n};\n\nfunction expectedException(actual, expected) {\n  if (!actual || !expected) {\n    return false;\n  }\n\n  if (Object.prototype.toString.call(expected) == '[object RegExp]') {\n    return expected.test(actual);\n  } else if (actual instanceof expected) {\n    return true;\n  } else if (expected.call({}, actual) === true) {\n    return true;\n  }\n\n  return false;\n}\n\nfunction _throws(shouldThrow, block, expected, message) {\n  var actual;\n\n  if (util.isString(expected)) {\n    message = expected;\n    expected = null;\n  }\n\n  try {\n    block();\n  } catch (e) {\n    actual = e;\n  }\n\n  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +\n            (message ? ' ' + message : '.');\n\n  if (shouldThrow && !actual) {\n    fail(actual, expected, 'Missing expected exception' + message);\n  }\n\n  if (!shouldThrow && expectedException(actual, expected)) {\n    fail(actual, expected, 'Got unwanted exception' + message);\n  }\n\n  if ((shouldThrow && actual && expected &&\n      !expectedException(actual, expected)) || (!shouldThrow && actual)) {\n    throw actual;\n  }\n}\n\n// 11. Expected to throw an error:\n// assert.throws(block, Error_opt, message_opt);\n\nassert.throws = function(block, /*optional*/error, /*optional*/message) {\n  _throws.apply(this, [true].concat(pSlice.call(arguments)));\n};\n\n// EXTENSION! This is annoying to write outside this module.\nassert.doesNotThrow = function(block, /*optional*/message) {\n  _throws.apply(this, [false].concat(pSlice.call(arguments)));\n};\n\nassert.ifError = function(err) { if (err) {throw err;}};\n},{\"_shims\":5,\"util\":7}],7:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg instanceof Buffer;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":5}]},{},[])\n;;module.exports=require(\"buffer-browserify\")\n\n},{}],36:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.8.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så']\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+',\n        _steps: ['giveth', 'whilst', 'thence']\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"W+dgdo\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":35,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":35,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":31}],35:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"W+dgdo\"])\n;"
  },
  {
    "path": "dist/yadda-0.8.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"3V0FPO\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":35,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":35,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":31}],35:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.8.6.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"3V0FPO\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":35,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":35,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":31}],35:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":13,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"3V0FPO\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":35,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":35,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":31}],35:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":28}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":21,\"./parsers/index\":24,\"./plugins/index\":27,\"./shims/index\":28}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":18}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":18}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],19:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":18}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":18}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./French\":17,\"./Language\":18,\"./Norwegian\":19,\"./Pirate\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":13,\"../localisation/English\":16}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],24:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":22,\"./StepParser\":23}],25:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":33,\"yadda\":\"3V0FPO\"}],26:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":22,\"fs\":33}],27:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":25,\"./MochaPlugin\":26}],28:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":29,\"./phantom-path\":30,\"./phantom-process\":31,\"__browserify_process\":36,\"fs\":33,\"path\":34}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":33,\"path\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":33}],32:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],33:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],34:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":36,\"_shims\":32,\"util\":35}],35:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":32}],36:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.10.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.10 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.11.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.11 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":28}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":21,\"./parsers/index\":24,\"./plugins/index\":27,\"./shims/index\":28}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":18}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":18}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],19:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":18}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":18}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./French\":17,\"./Language\":18,\"./Norwegian\":19,\"./Pirate\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":13,\"../localisation/English\":16}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],24:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":22,\"./StepParser\":23}],25:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":33,\"yadda\":\"3V0FPO\"}],26:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":22,\"fs\":33}],27:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":25,\"./MochaPlugin\":26}],28:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":29,\"./phantom-path\":30,\"./phantom-process\":31,\"__browserify_process\":36,\"fs\":33,\"path\":34}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":33,\"path\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":33}],32:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],33:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],34:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":36,\"_shims\":32,\"util\":35}],35:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":32}],36:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":28}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":21,\"./parsers/index\":24,\"./plugins/index\":27,\"./shims/index\":28}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":18}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":18}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],19:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":18}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":18}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./French\":17,\"./Language\":18,\"./Norwegian\":19,\"./Pirate\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":13,\"../localisation/English\":16}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],24:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":22,\"./StepParser\":23}],25:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":33,\"yadda\":\"3V0FPO\"}],26:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":22,\"fs\":33}],27:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":25,\"./MochaPlugin\":26}],28:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":29,\"./phantom-path\":30,\"./phantom-process\":31,\"__browserify_process\":36,\"fs\":33,\"path\":34}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":33,\"path\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":33}],32:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],33:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],34:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":36,\"_shims\":32,\"util\":35}],35:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":32}],36:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":29}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":22,\"./parsers/index\":25,\"./plugins/index\":28,\"./shims/index\":29}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":19}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],25:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":23,\"./StepParser\":24}],26:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":34,\"yadda\":\"3V0FPO\"}],27:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":23,\"fs\":34}],28:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":26,\"./MochaPlugin\":27}],29:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":30,\"./phantom-path\":31,\"./phantom-process\":32,\"__browserify_process\":37,\"fs\":34,\"path\":35}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":34,\"path\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":34}],33:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],34:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],35:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":37,\"_shims\":33,\"util\":36}],36:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":33}],37:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":29}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":22,\"./parsers/index\":25,\"./plugins/index\":28,\"./shims/index\":29}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],25:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":23,\"./StepParser\":24}],26:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":34,\"yadda\":\"3V0FPO\"}],27:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":23,\"fs\":34}],28:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":26,\"./MochaPlugin\":27}],29:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":30,\"./phantom-path\":31,\"./phantom-process\":32,\"__browserify_process\":37,\"fs\":34,\"path\":35}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":34,\"path\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":34}],33:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],34:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],35:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":37,\"_shims\":33,\"util\":36}],36:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":33}],37:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.6.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":29}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":22,\"./parsers/index\":25,\"./plugins/index\":28,\"./shims/index\":29}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],25:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":23,\"./StepParser\":24}],26:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":34,\"yadda\":\"3V0FPO\"}],27:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":23,\"fs\":34}],28:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":26,\"./MochaPlugin\":27}],29:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":30,\"./phantom-path\":31,\"./phantom-process\":32,\"__browserify_process\":37,\"fs\":34,\"path\":35}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":34,\"path\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":34}],33:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],34:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],35:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":37,\"_shims\":33,\"util\":36}],36:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":33}],37:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.7.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.8.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.8 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-0.9.9.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.9 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-1.0.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.0.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.0.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.0.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],47:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.1.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.1.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],47:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.1.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.1.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],47:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.2.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.2.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],47:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.3.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.3.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.3.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.3.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.4.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.4.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.5.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.5.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-1.5.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.5.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-2.0.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 2.0.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        var leading_spaces = '^(?:\\\\s)*';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-2.0.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libs) {\n        libraries.push_all(libs);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 2.0.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        var leading_spaces = '^(?:\\\\s)*';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-2.1.0.js",
    "content": "require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libs) {\n        libraries.push_all(libs);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){(function (){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this)}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 2.1.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        var leading_spaces = '^(?:\\\\s)*';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){(function (){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){(function (){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this)}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){(function (){\n// 'path' module extracted from Node.js v8.11.1 (only the posix part)\n// transplited with Babel\n\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nfunction assertPath(path) {\n  if (typeof path !== 'string') {\n    throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));\n  }\n}\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeStringPosix(path, allowAboveRoot) {\n  var res = '';\n  var lastSegmentLength = 0;\n  var lastSlash = -1;\n  var dots = 0;\n  var code;\n  for (var i = 0; i <= path.length; ++i) {\n    if (i < path.length)\n      code = path.charCodeAt(i);\n    else if (code === 47 /*/*/)\n      break;\n    else\n      code = 47 /*/*/;\n    if (code === 47 /*/*/) {\n      if (lastSlash === i - 1 || dots === 1) {\n        // NOOP\n      } else if (lastSlash !== i - 1 && dots === 2) {\n        if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {\n          if (res.length > 2) {\n            var lastSlashIndex = res.lastIndexOf('/');\n            if (lastSlashIndex !== res.length - 1) {\n              if (lastSlashIndex === -1) {\n                res = '';\n                lastSegmentLength = 0;\n              } else {\n                res = res.slice(0, lastSlashIndex);\n                lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n              }\n              lastSlash = i;\n              dots = 0;\n              continue;\n            }\n          } else if (res.length === 2 || res.length === 1) {\n            res = '';\n            lastSegmentLength = 0;\n            lastSlash = i;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          if (res.length > 0)\n            res += '/..';\n          else\n            res = '..';\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0)\n          res += '/' + path.slice(lastSlash + 1, i);\n        else\n          res = path.slice(lastSlash + 1, i);\n        lastSegmentLength = i - lastSlash - 1;\n      }\n      lastSlash = i;\n      dots = 0;\n    } else if (code === 46 /*.*/ && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\n\nfunction _format(sep, pathObject) {\n  var dir = pathObject.dir || pathObject.root;\n  var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');\n  if (!dir) {\n    return base;\n  }\n  if (dir === pathObject.root) {\n    return dir + base;\n  }\n  return dir + sep + base;\n}\n\nvar posix = {\n  // path.resolve([from ...], to)\n  resolve: function resolve() {\n    var resolvedPath = '';\n    var resolvedAbsolute = false;\n    var cwd;\n\n    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n      var path;\n      if (i >= 0)\n        path = arguments[i];\n      else {\n        if (cwd === undefined)\n          cwd = process.cwd();\n        path = cwd;\n      }\n\n      assertPath(path);\n\n      // Skip empty entries\n      if (path.length === 0) {\n        continue;\n      }\n\n      resolvedPath = path + '/' + resolvedPath;\n      resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    }\n\n    // At this point the path should be resolved to a full absolute path, but\n    // handle relative paths to be safe (might happen when process.cwd() fails)\n\n    // Normalize the path\n    resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);\n\n    if (resolvedAbsolute) {\n      if (resolvedPath.length > 0)\n        return '/' + resolvedPath;\n      else\n        return '/';\n    } else if (resolvedPath.length > 0) {\n      return resolvedPath;\n    } else {\n      return '.';\n    }\n  },\n\n  normalize: function normalize(path) {\n    assertPath(path);\n\n    if (path.length === 0) return '.';\n\n    var isAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;\n\n    // Normalize the path\n    path = normalizeStringPosix(path, !isAbsolute);\n\n    if (path.length === 0 && !isAbsolute) path = '.';\n    if (path.length > 0 && trailingSeparator) path += '/';\n\n    if (isAbsolute) return '/' + path;\n    return path;\n  },\n\n  isAbsolute: function isAbsolute(path) {\n    assertPath(path);\n    return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;\n  },\n\n  join: function join() {\n    if (arguments.length === 0)\n      return '.';\n    var joined;\n    for (var i = 0; i < arguments.length; ++i) {\n      var arg = arguments[i];\n      assertPath(arg);\n      if (arg.length > 0) {\n        if (joined === undefined)\n          joined = arg;\n        else\n          joined += '/' + arg;\n      }\n    }\n    if (joined === undefined)\n      return '.';\n    return posix.normalize(joined);\n  },\n\n  relative: function relative(from, to) {\n    assertPath(from);\n    assertPath(to);\n\n    if (from === to) return '';\n\n    from = posix.resolve(from);\n    to = posix.resolve(to);\n\n    if (from === to) return '';\n\n    // Trim any leading backslashes\n    var fromStart = 1;\n    for (; fromStart < from.length; ++fromStart) {\n      if (from.charCodeAt(fromStart) !== 47 /*/*/)\n        break;\n    }\n    var fromEnd = from.length;\n    var fromLen = fromEnd - fromStart;\n\n    // Trim any leading backslashes\n    var toStart = 1;\n    for (; toStart < to.length; ++toStart) {\n      if (to.charCodeAt(toStart) !== 47 /*/*/)\n        break;\n    }\n    var toEnd = to.length;\n    var toLen = toEnd - toStart;\n\n    // Compare paths to find the longest common path from root\n    var length = fromLen < toLen ? fromLen : toLen;\n    var lastCommonSep = -1;\n    var i = 0;\n    for (; i <= length; ++i) {\n      if (i === length) {\n        if (toLen > length) {\n          if (to.charCodeAt(toStart + i) === 47 /*/*/) {\n            // We get here if `from` is the exact base path for `to`.\n            // For example: from='/foo/bar'; to='/foo/bar/baz'\n            return to.slice(toStart + i + 1);\n          } else if (i === 0) {\n            // We get here if `from` is the root\n            // For example: from='/'; to='/foo'\n            return to.slice(toStart + i);\n          }\n        } else if (fromLen > length) {\n          if (from.charCodeAt(fromStart + i) === 47 /*/*/) {\n            // We get here if `to` is the exact base path for `from`.\n            // For example: from='/foo/bar/baz'; to='/foo/bar'\n            lastCommonSep = i;\n          } else if (i === 0) {\n            // We get here if `to` is the root.\n            // For example: from='/foo'; to='/'\n            lastCommonSep = 0;\n          }\n        }\n        break;\n      }\n      var fromCode = from.charCodeAt(fromStart + i);\n      var toCode = to.charCodeAt(toStart + i);\n      if (fromCode !== toCode)\n        break;\n      else if (fromCode === 47 /*/*/)\n        lastCommonSep = i;\n    }\n\n    var out = '';\n    // Generate the relative path based on the path difference between `to`\n    // and `from`\n    for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n      if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {\n        if (out.length === 0)\n          out += '..';\n        else\n          out += '/..';\n      }\n    }\n\n    // Lastly, append the rest of the destination (`to`) path that comes after\n    // the common path parts\n    if (out.length > 0)\n      return out + to.slice(toStart + lastCommonSep);\n    else {\n      toStart += lastCommonSep;\n      if (to.charCodeAt(toStart) === 47 /*/*/)\n        ++toStart;\n      return to.slice(toStart);\n    }\n  },\n\n  _makeLong: function _makeLong(path) {\n    return path;\n  },\n\n  dirname: function dirname(path) {\n    assertPath(path);\n    if (path.length === 0) return '.';\n    var code = path.charCodeAt(0);\n    var hasRoot = code === 47 /*/*/;\n    var end = -1;\n    var matchedSlash = true;\n    for (var i = path.length - 1; i >= 1; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          if (!matchedSlash) {\n            end = i;\n            break;\n          }\n        } else {\n        // We saw the first non-path separator\n        matchedSlash = false;\n      }\n    }\n\n    if (end === -1) return hasRoot ? '/' : '.';\n    if (hasRoot && end === 1) return '//';\n    return path.slice(0, end);\n  },\n\n  basename: function basename(path, ext) {\n    if (ext !== undefined && typeof ext !== 'string') throw new TypeError('\"ext\" argument must be a string');\n    assertPath(path);\n\n    var start = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i;\n\n    if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n      if (ext.length === path.length && ext === path) return '';\n      var extIdx = ext.length - 1;\n      var firstNonSlashEnd = -1;\n      for (i = path.length - 1; i >= 0; --i) {\n        var code = path.charCodeAt(i);\n        if (code === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else {\n          if (firstNonSlashEnd === -1) {\n            // We saw the first non-path separator, remember this index in case\n            // we need it if the extension ends up not matching\n            matchedSlash = false;\n            firstNonSlashEnd = i + 1;\n          }\n          if (extIdx >= 0) {\n            // Try to match the explicit extension\n            if (code === ext.charCodeAt(extIdx)) {\n              if (--extIdx === -1) {\n                // We matched the extension, so mark this as the end of our path\n                // component\n                end = i;\n              }\n            } else {\n              // Extension does not match, so our result is the entire path\n              // component\n              extIdx = -1;\n              end = firstNonSlashEnd;\n            }\n          }\n        }\n      }\n\n      if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;\n      return path.slice(start, end);\n    } else {\n      for (i = path.length - 1; i >= 0; --i) {\n        if (path.charCodeAt(i) === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else if (end === -1) {\n          // We saw the first non-path separator, mark this as the end of our\n          // path component\n          matchedSlash = false;\n          end = i + 1;\n        }\n      }\n\n      if (end === -1) return '';\n      return path.slice(start, end);\n    }\n  },\n\n  extname: function extname(path) {\n    assertPath(path);\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n    for (var i = path.length - 1; i >= 0; --i) {\n      var code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1)\n            startDot = i;\n          else if (preDotState !== 1)\n            preDotState = 1;\n      } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n        // We saw a non-dot character immediately before the dot\n        preDotState === 0 ||\n        // The (right-most) trimmed path component is exactly '..'\n        preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      return '';\n    }\n    return path.slice(startDot, end);\n  },\n\n  format: function format(pathObject) {\n    if (pathObject === null || typeof pathObject !== 'object') {\n      throw new TypeError('The \"pathObject\" argument must be of type Object. Received type ' + typeof pathObject);\n    }\n    return _format('/', pathObject);\n  },\n\n  parse: function parse(path) {\n    assertPath(path);\n\n    var ret = { root: '', dir: '', base: '', ext: '', name: '' };\n    if (path.length === 0) return ret;\n    var code = path.charCodeAt(0);\n    var isAbsolute = code === 47 /*/*/;\n    var start;\n    if (isAbsolute) {\n      ret.root = '/';\n      start = 1;\n    } else {\n      start = 0;\n    }\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i = path.length - 1;\n\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n\n    // Get non-dir info\n    for (; i >= start; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;\n        } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n    // We saw a non-dot character immediately before the dot\n    preDotState === 0 ||\n    // The (right-most) trimmed path component is exactly '..'\n    preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      if (end !== -1) {\n        if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);\n      }\n    } else {\n      if (startPart === 0 && isAbsolute) {\n        ret.name = path.slice(1, startDot);\n        ret.base = path.slice(1, end);\n      } else {\n        ret.name = path.slice(startPart, startDot);\n        ret.base = path.slice(startPart, end);\n      }\n      ret.ext = path.slice(startDot, end);\n    }\n\n    if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';\n\n    return ret;\n  },\n\n  sep: '/',\n  delimiter: ':',\n  win32: null,\n  posix: null\n};\n\nposix.posix = posix;\n\nmodule.exports = posix;\n\n}).call(this)}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-2.1.1.js",
    "content": "require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\n'use strict';\n\nvar fn = require('./fn');\n\nmodule.exports = function (obj) {\n  function ensure_array(obj) {\n    var array = obj ? [].concat(obj) : [];\n    array.in_array = fn.curry(array, in_array, array);\n    array.each = fn.curry(array, each, array);\n    array.each_async = fn.curry(array, each_async, array);\n    array.collect = fn.curry(array, collect, array);\n    array.collect_async = fn.curry(array, collect_async, array);\n    array.flatten = fn.curry(array, flatten, array);\n    array.inject = fn.curry(array, inject, array);\n    array.push_all = fn.curry(array, push_all, array);\n    array.fill = fn.curry(array, fill, array);\n    array.find_all = fn.curry(array, find_all, array);\n    array.find = fn.curry(array, find, array);\n    array.last = fn.curry(array, last, array);\n    array.naked = fn.curry(array, naked, array);\n    return array;\n  }\n\n  function is_array(obj) {\n    return Object.prototype.toString.call(obj) === '[object Array]';\n  }\n\n  function in_array(items, item) {\n    for (var i = 0; i < items.length; i++) {\n      if (items[i] === item) {\n        return true;\n      }\n    }\n  }\n\n  function flatten(items) {\n    if (!is_array(items)) return [items];\n    if (items.length === 0) return items;\n    var head = flatten(items[0]);\n    var tail = flatten(items.slice(1));\n    return ensure_array(head.concat(tail));\n  }\n\n  function each(items, iterator) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(items[i], i);\n    }\n    return result;\n  }\n\n  function each_async(items, iterator, callback) {\n    callback = callback || fn.noop;\n    if (!items.length) return callback();\n    var index = 0;\n    var iterate = function () {\n      iterator(items[index], index, function (err, result) {\n        if (err) return callback(err);\n        if (++index >= items.length) return callback(null, result);\n        iterate();\n      });\n    };\n    iterate();\n  }\n\n  function collect(items, iterator) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      results.push(iterator(items[i], i));\n    }\n    return results;\n  }\n\n  function collect_async(items, iterator, callback) {\n    var results = ensure_array();\n    each_async(\n      items,\n      function (item, index, each_callback) {\n        iterator(item, index, function (err) {\n          if (err) return each_callback(err);\n          results.push_all(Array.prototype.splice.call(arguments, 1));\n          each_callback();\n        });\n      },\n      function (err) {\n        if (err) return callback(err);\n        callback(null, results);\n      }\n    );\n  }\n\n  function inject(items, default_value, iterator) {\n    var result = default_value;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(result, items[i]);\n    }\n    return result;\n  }\n\n  function push_all(items, more_items) {\n    more_items = more_items ? [].concat(more_items) : [];\n    for (var i = 0; i < more_items.length; i++) {\n      items.push(more_items[i]);\n    }\n    return items;\n  }\n\n  function fill(items, item, num) {\n    for (var i = 0; i < num; i++) {\n      items.push(item);\n    }\n    return items;\n  }\n\n  function find_all(items, test) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        results.push(items[i]);\n      }\n    }\n    return results;\n  }\n\n  function find(items, test) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        result = items[i];\n        break;\n      }\n    }\n    return result;\n  }\n\n  function last(items) {\n    return items[items.length - 1];\n  }\n\n  function naked(items) {\n    return [].concat(items);\n  }\n\n  return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n'use strict';\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function (step, macros, last_macro) {\n  var results = [];\n\n  this.validate = function () {\n    if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n    if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n    return { step: step, valid: true, winner: this.winner() };\n  };\n\n  this.clear_winner = function () {\n    if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n    if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n    return this.winner();\n  };\n\n  function is_undefined() {\n    return results.length === 0;\n  }\n\n  function is_ambiguous() {\n    return results.length > 1 && results[0].score.equals(results[1].score);\n  }\n\n  this.winner = function () {\n    return results[0].macro;\n  };\n\n  function winning_patterns() {\n    return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n  }\n\n  function rank(step, macros) {\n    results = macros\n      .collect(function (macro) {\n        return {\n          macro: macro,\n          score: new MultiScore([new LevenshteinDistanceScore(step, macro.levenshtein_signature()), new SameLibraryScore(macro, last_macro)]),\n        };\n      })\n      .sort(by_ascending_score);\n  }\n\n  function by_ascending_score(a, b) {\n    return b.score.compare(a.score);\n  }\n\n  function by_winning_score(result) {\n    return result.score.equals(results[0].score);\n  }\n\n  function macro_signatures(result) {\n    return result.macro.toString();\n  }\n\n  rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n'use strict';\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function (properties) {\n  // I was previously getting some weird errors using instanceof to determine if\n  // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n  this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n  this.properties = {};\n\n  this.merge = function (other) {\n    if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n    return new Context(this.properties)._merge(other);\n  };\n\n  this._merge = function (other) {\n    for (var key in other) {\n      this.properties[key] = other[key];\n    }\n    return this;\n  };\n\n  this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function (prefix) {\n  // eslint-disable-next-line no-redeclare\n  var prefix = prefix || '$';\n  var definitions = {};\n  var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n  var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n  var _this = this;\n\n  this.define = function (term, pattern, converters) {\n    if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n    if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n    if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n    if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n    definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n    return this;\n  };\n\n  this.merge = function (other) {\n    if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n    return new Dictionary(prefix)._merge(this)._merge(other);\n  };\n\n  this._merge = function (other) {\n    other.each(function (term, definition) {\n      _this.define(term, definition.pattern);\n    });\n    return this;\n  };\n\n  this._prefix = function () {\n    return prefix;\n  };\n\n  this.each = function (callback) {\n    for (var term in definitions) {\n      callback(term, definitions[term]);\n    }\n  };\n\n  this.expand = function (signature, already_expanding) {\n    var text = normalise(signature);\n    return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) } : { pattern: text, converters: get_converters(text) };\n  };\n\n  function expand_sub_terms(text, already_expanding) {\n    return get_sub_terms(text).each(function (sub_term) {\n      if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n      var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n      text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n      return text;\n    });\n  }\n\n  function get_sub_terms(text) {\n    return term_grouping_pattern.groups(text);\n  }\n\n  function expand_sub_term(sub_term, already_expanding) {\n    var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n    return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n  }\n\n  function normalise(pattern) {\n    return pattern.toString().replace(/^\\/|\\/$/g, '');\n  }\n\n  function is_defined(term) {\n    return !!definitions[term];\n  }\n\n  function is_expandable(text) {\n    return term_grouping_pattern.test(text);\n  }\n\n  function is_compatible(converters, pattern) {\n    return count_converter_arguments(converters) === count_matching_groups(pattern);\n  }\n\n  function get_converters(text) {\n    return $(text.split(term_splitting_pattern)).inject($(), function (converters, fragment) {\n      return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment) : get_matching_group_converters(fragment));\n    });\n  }\n\n  function get_matching_group_converters(text) {\n    return $().fill(pass_through_converter, count_matching_groups(text));\n  }\n\n  function get_sub_term_converters(text) {\n    return get_sub_terms(text).inject($(), function (converters, sub_term) {\n      return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters) : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n    });\n  }\n\n  function count_matching_groups(pattern) {\n    return new RegExp(pattern + '|').exec('').length - 1;\n  }\n\n  function count_converter_arguments(converters) {\n    return $(converters).inject(0, function (sum, converter) {\n      return sum + converter.length - 1;\n    });\n  }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n  var event_handlers = $();\n\n  this.send = function (event_name, event_data, next) {\n    if (arguments.length === 1) return this.send(event_name, {});\n    if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n    notify_handlers(event_name, event_data);\n    next && next();\n    return this;\n  };\n\n  this.on = function (event_pattern, callback) {\n    event_handlers.push({ pattern: event_pattern, callback: callback });\n    return this;\n  };\n\n  var notify_handlers = function (event_name, event_data) {\n    find_handlers(event_name).each(function (callback) {\n      callback({ name: event_name, data: event_data });\n    });\n  };\n\n  var find_handlers = function (event_name) {\n    return event_handlers\n      .find_all(function (handler) {\n        return new RegExp(handler.pattern).test(event_name);\n      })\n      .collect(function (handler) {\n        return handler.callback;\n      });\n  };\n}\n\nfunction instance() {\n  return event_bus;\n}\n\nmodule.exports = {\n  instance: instance,\n  ON_SCENARIO: '__ON_SCENARIO__',\n  ON_STEP: '__ON_STEP__',\n  ON_EXECUTE: '__ON_EXECUTE__',\n  ON_DEFINE: '__ON_DEFINE__',\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n'use strict';\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function (directories) {\n  this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n'use strict';\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function (directories, patterns) {\n  // eslint-disable-next-line no-redeclare\n  var patterns = patterns || /.*/;\n\n  this.each = function (fn) {\n    this.list().forEach(fn);\n  };\n\n  this.list = function () {\n    return $(directories).inject($(), function (files, directory) {\n      return files.concat(list_files(directory).find_all(by_pattern));\n    });\n  };\n\n  var list_files = function (directory) {\n    return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n  };\n\n  var list_immediate_files = function (directory) {\n    return ls(directory).find_all(by_file);\n  };\n\n  var list_sub_directory_files = function (directory) {\n    return ls(directory)\n      .find_all(by_directory)\n      .inject($(), function (files, directory) {\n        return files.concat(list_files(directory));\n      });\n  };\n\n  var ls = function (directory) {\n    if (!fs.existsSync(directory)) return $();\n    return $(fs.readdirSync(directory)).collect(function (file) {\n      return path.join(directory, file);\n    });\n  };\n\n  var by_file = function (file) {\n    return !by_directory(file);\n  };\n\n  var by_directory = function (file) {\n    return fs.statSync(file).isDirectory();\n  };\n\n  var by_pattern = function (filename) {\n    return $(patterns).find(function (pattern) {\n      return new RegExp(pattern).test(filename);\n    });\n  };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n'use strict';\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function (libraries) {\n  // eslint-disable-next-line no-redeclare\n  var libraries = $(libraries);\n  var event_bus = EventBus.instance();\n  var last_macro;\n  var _this = this;\n\n  this.requires = function (libs) {\n    libraries.push_all(libs);\n    return this;\n  };\n\n  this.validate = function (scenario) {\n    var results = $(scenario).collect(function (step) {\n      var report = _this.rank_macros(step).validate();\n      last_macro = report.winner;\n      return report;\n    });\n    if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n  };\n\n  function by_invalid_step(result) {\n    return !result.valid;\n  }\n\n  function validation_report(result) {\n    return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n  }\n\n  this.interpret = function (scenario, scenario_context, next) {\n    scenario_context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n    var iterator = make_step_iterator(scenario_context, next);\n    $(scenario).each_async(iterator, next);\n  };\n\n  var make_step_iterator = function (scenario_context, next) {\n    var iterator = function (step, index, callback) {\n      _this.interpret_step(step, scenario_context, callback);\n    };\n    return next ? iterator : fn.asynchronize(null, iterator);\n  };\n\n  this.interpret_step = function (step, scenario_context, next) {\n    var context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n    var macro = this.rank_macros(step).clear_winner();\n    last_macro = macro;\n    macro.interpret(step, context || {}, next);\n  };\n\n  this.rank_macros = function (step) {\n    return new Competition(step, compatible_macros(step), last_macro);\n  };\n\n  var compatible_macros = function (step) {\n    return libraries.inject([], function (macros, library) {\n      return macros.concat(library.find_compatible_macros(step));\n    });\n  };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n'use strict';\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function (dictionary) {\n  // eslint-disable-next-line no-redeclare\n  var dictionary = dictionary || new Dictionary();\n  var macros = $();\n  var _this = this;\n\n  this.define = function (signatures, fn, macro_context, options) {\n    $(signatures).each(function (signature) {\n      define_macro(signature, fn, macro_context, options);\n    });\n    return this;\n  };\n\n  var define_macro = function (signature, fn, macro_context, options) {\n    if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n    macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n  };\n\n  this.get_macro = function (signature) {\n    return macros.find(function (other_macro) {\n      return other_macro.is_identified_by(signature);\n    });\n  };\n\n  this.find_compatible_macros = function (step) {\n    return macros.find_all(function (macro) {\n      return macro.can_interpret(step);\n    });\n  };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n'use strict';\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function (signature, parsed_signature, macro, macro_context, library, options) {\n  /* eslint-disable no-redeclare */\n  var signature = normalise(signature);\n  var signature_pattern = new RegularExpression(parsed_signature.pattern);\n  var macro = macro || fn.async_noop;\n  var event_bus = EventBus.instance();\n  var options = options || {};\n  /* eslint-enable no-redeclare */\n\n  this.library = library;\n\n  this.is_identified_by = function (other_signature) {\n    return signature === normalise(other_signature);\n  };\n\n  this.can_interpret = function (step) {\n    return signature_pattern.test(step);\n  };\n\n  this.interpret = function (step, scenario_context, next) {\n    var context = new Context({ step: step }).merge(macro_context).merge(scenario_context);\n    convert(signature_pattern.groups(step), function (err, args) {\n      if (err) return next(err);\n      event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n      var result;\n      try {\n        result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n      } catch (err) {\n        if (next) return next(err);\n        throw err;\n      }\n      if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n      if (is_sync(args)) return next && next();\n    });\n  };\n\n  this.is_sibling = function (other_macro) {\n    return other_macro && other_macro.defined_in(library);\n  };\n\n  this.defined_in = function (other_library) {\n    return library === other_library;\n  };\n\n  this.levenshtein_signature = function () {\n    return signature_pattern.without_expressions();\n  };\n\n  this.toString = function () {\n    return signature;\n  };\n\n  function is_promise(result) {\n    if (options.mode) return options.mode === 'promise';\n    return result && result.then;\n  }\n\n  function is_sync(args) {\n    if (options.mode) return options.mode === 'sync';\n    return macro !== fn.async_noop && macro.length !== args.length + 1;\n  }\n\n  function normalise(signature) {\n    return new RegExp(signature).toString();\n  }\n\n  function convert(args, next) {\n    var index = 0;\n    return $(parsed_signature.converters)\n      .collect(function (converter) {\n        return function (callback) {\n          converter.apply(null, args.slice(index, (index += converter.length - 1)).concat(callback));\n        };\n      })\n      .collect_async(function (converter, index, callback) {\n        converter(callback);\n      }, next);\n  }\n\n  event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){(function (){\n'use strict';\n\nmodule.exports = Platform;\n\nfunction Platform() {\n  function get_container() {\n    /* eslint-disable no-undef */\n    if (is_browser()) return window;\n    if (is_phantom()) return phantom;\n    if (is_node()) return global;\n    /* eslint-enable no-undef */\n  }\n\n  function is_node() {\n    return typeof process !== 'undefined' && typeof global !== 'undefined' && typeof __dirname !== 'undefined';\n  }\n\n  function is_browser() {\n    return typeof window !== 'undefined';\n  }\n\n  function is_phantom() {\n    return typeof phantom !== 'undefined';\n  }\n\n  function is_karma() {\n    return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n  }\n\n  return {\n    get_container: get_container,\n    is_node: is_node,\n    is_browser: is_browser,\n    is_phantom: is_phantom,\n    is_karma: is_karma,\n  };\n}\n\n}).call(this)}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function (pattern_or_regexp) {\n  var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n  var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n  var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n  var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n  var non_word_tokens_pattern = /[^\\w\\s]/g;\n  var regexp = new RegExp(pattern_or_regexp);\n\n  this.test = function (text) {\n    var result = regexp.test(text);\n    this.reset();\n    return result;\n  };\n\n  this.groups = function (text) {\n    var results = $();\n    var match = regexp.exec(text);\n    while (match) {\n      var groups = match.slice(1, match.length);\n      results.push(groups);\n      match = regexp.global && regexp.exec(text);\n    }\n    this.reset();\n    return results.flatten();\n  };\n\n  this.reset = function () {\n    regexp.lastIndex = 0;\n    return this;\n  };\n\n  this.without_expressions = function () {\n    return regexp.source.replace(groups_pattern, '$1').replace(sets_pattern, '$1').replace(repetitions_pattern, '$1').replace(regex_aliases_pattern, '$1').replace(non_word_tokens_pattern, '');\n  };\n\n  this.equals = function (other) {\n    return this.toString() === other.toString();\n  };\n\n  this.toString = function () {\n    return '/' + regexp.source + '/';\n  };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  trim: function trim(text) {\n    return text.replace(/^\\s+|\\s+$/g, '');\n  },\n  rtrim: function rtrim(text) {\n    return text.replace(/\\s+$/g, '');\n  },\n  isBlank: function isBlank(text) {\n    return /^\\s*$/g.test(text);\n  },\n  isNotBlank: function isNotBlank(text) {\n    return !this.isBlank(text);\n  },\n  indentation: function indentation(text) {\n    var match = /^(\\s*)/.exec(text);\n    return (match && match[0].length) || 0;\n  },\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n'use strict';\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function (libraries, interpreter_context) {\n  if (!(this instanceof Yadda)) {\n    return new Yadda(libraries, interpreter_context);\n  }\n\n  this.interpreter = new Interpreter(libraries);\n\n  this.requires = function (libraries) {\n    this.interpreter.requires(libraries);\n    return this;\n  };\n\n  this.yadda = function (scenario, scenario_context, next) {\n    if (arguments.length === 0) return this;\n    if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n    this.interpreter.validate(scenario);\n    this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n  };\n\n  // Not everyone shares my sense of humour re the recursive api :(\n  // See https://github.com/acuminous/yadda/issues/111\n  this.run = this.yadda;\n\n  this.toString = function () {\n    return 'Yadda 2.1.1 Copyright 2010 Stephen Cresswell';\n  };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function date_converter(value, next) {\n  var converted = Date.parse(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n  return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function float_converter(value, next) {\n  var converted = parseFloat(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n  return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  date: require('./date-converter'),\n  integer: require('./integer-converter'),\n  float: require('./float-converter'),\n  list: require('./list-converter'),\n  table: require('./table-converter'),\n  pass_through: require('./pass-through-converter'),\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function integer_converter(value, next) {\n  var converted = parseInt(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n  return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function list_converter(value, next) {\n  return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function pass_through_converter(value, next) {\n  return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\nmodule.exports = function table_converter(value, next) {\n  var rows = value.split(/\\n/);\n  var headings = parse_headings(rows.shift());\n  var handler = is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n  var table = $();\n\n  try {\n    $(rows).each(handler);\n    next(null, collapse(table));\n  } catch (err) {\n    next(err);\n  }\n\n  function handle_single_line_row(row) {\n    if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n    start_new_row();\n    parse_fields(row);\n  }\n\n  function handle_multiline_row(row) {\n    if (is_horizinal_separator(row)) return start_new_row();\n    parse_fields(row);\n  }\n\n  function parse_headings(row) {\n    return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX))\n      .collect(function (value) {\n        return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n      })\n      .naked();\n  }\n\n  function is_horizinal_separator(row) {\n    return DASH_REGEX.test(row);\n  }\n\n  function start_new_row() {\n    table.push({});\n  }\n\n  function parse_fields(row) {\n    var fields = table.last();\n    $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function (field, index) {\n      var column = headings[index].text;\n      var indentation = headings[index].indentation;\n      var text = StringUtils.rtrim(field.substr(indentation));\n      if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n      fields[column] = (fields[column] || []).concat(text);\n    });\n  }\n\n  function collapse(table) {\n    return table\n      .collect(function (row) {\n        var new_row = {};\n        for (var heading in row) {\n          new_row[heading] = row[heading].join('\\n');\n        }\n        return new_row;\n      })\n      .naked();\n  }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  var slice = Array.prototype.slice;\n\n  function curry(ctx, fn) {\n    var args = slice.call(arguments, 2);\n    return function () {\n      return fn.apply(ctx, args.concat(slice.call(arguments)));\n    };\n  }\n\n  function invoke(fn, ctx, args) {\n    return fn.apply(ctx, args);\n  }\n\n  function is_function(object) {\n    var getType = {};\n    return object && getType.toString.call(object) === '[object Function]';\n  }\n\n  function noop() {}\n\n  function noargs(fn) {\n    return function () {\n      return fn();\n    };\n  }\n\n  function asynchronize(ctx, fn) {\n    return function () {\n      var next = slice.call(arguments, arguments.length - 1)[0];\n      var args = slice.call(arguments, 0, arguments.length - 2);\n      fn.apply(ctx, args);\n      if (next) next();\n    };\n  }\n\n  return {\n    noop: noop,\n    noargs: noargs,\n    async_noop: asynchronize(null, noop),\n    asynchronize: asynchronize,\n    is_function: is_function,\n    curry: curry,\n    invoke: invoke,\n  };\n})();\n\n},{}],23:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature|功能',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\n    examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\n    pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\n    only: '(?:[Oo]nly|仅仅?)',\n    background: '[Bb]ackground|背景|前提',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Chinese', vocabulary);\n})();\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n    scenario: '(?:[Ss]cenario|[Gg|eval)',\n    examples: '(?:[Vv]oorbeelden?)',\n    pending: '(?:[Tt]odo|[Mm]oet nog)',\n    only: '(?:[Aa]lleen)',\n    background: '(?:[Aa]chtergrond)',\n    given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n    when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n    then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n    examples: '(?:[Ee]xamples|[Ww]here)',\n    pending: '(?:[Pp]ending|[Tt]odo)',\n    only: '(?:[Oo]nly)',\n    background: '[Bb]ackground',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]onctionnalité)',\n    scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n    examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n    pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n    only: '(?:[Ss]eulement])',\n    background: '(?:[Cc]ontexte)',\n    given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n    when: \"(?:[Qq]uand|[Ll]orsqu'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)\",\n    then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n    _steps: ['given', 'when', 'then', 'soit', 'etantdonnees', 'etantdonnee', 'etantdonne', 'quand', 'lorsque', 'alors'],\n    // Also aliasing French verbs for given-when-then for signature-lookup\n    get soit() {\n      return this.given;\n    },\n    get etantdonnees() {\n      return this.given;\n    },\n    get etantdonnee() {\n      return this.given;\n    },\n    get etantdonne() {\n      return this.given;\n    },\n    get quand() {\n      return this.when;\n    },\n    get lorsque() {\n      return this.when;\n    },\n    get alors() {\n      return this.then;\n    },\n  };\n\n  return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n    scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n    examples: '(?:[Bb]eispiele?)',\n    pending: '(?:[Tt]odo|[Oo]ffen)',\n    only: '(?:[Nn]ur|[Ee]inzig)',\n    background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n    given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n    when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n    then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n'use strict';\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function (name, vocabulary) {\n  var _this = this;\n\n  // See http://github.com/acuminous/yadda#203\n  this.is_language = true;\n\n  this.library = function (dictionary) {\n    return _this.localise_library(new Library(dictionary));\n  };\n\n  this.localise_library = function (library) {\n    $(vocabulary._steps).each(function (keyword) {\n      library[keyword] = function (signatures, fn, ctx, options) {\n        return $(signatures).each(function (signature) {\n          signature = prefix_signature(_this.localise(keyword), signature);\n          return library.define(signature, fn, ctx, options);\n        });\n      };\n    });\n    return library;\n  };\n\n  var prefix_signature = function (prefix, signature) {\n    var regex_delimiters = new RegExp('^/|/$', 'g');\n    var start_of_signature = new RegExp(/^(?:\\^)?/);\n    var one_or_more_spaces = '\\\\s+';\n    var leading_spaces = '^(?:\\\\s)*';\n    return signature\n      .toString()\n      .replace(regex_delimiters, '')\n      .replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n  };\n\n  this.localise = function (keyword) {\n    if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n    return vocabulary[keyword];\n  };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ee]genskap',\n    scenario: '[Ss]cenario',\n    examples: '[Ee]ksempler',\n    pending: '[Aa]vventer',\n    only: '[Bb]are',\n    background: '[Bb]akgrunn',\n    given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n    when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n    then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n    _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n    // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n    get gitt() {\n      return this.given;\n    },\n    get når() {\n      return this.when;\n    },\n    get så() {\n      return this.then;\n    },\n  };\n\n  return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Tt]ale|[Yy]arn)',\n    scenario: '(?:[Aa]dventure|[Ss]ortie)',\n    examples: '[Ww]herest',\n    pending: '[Bb]rig',\n    only: '[Bb]lack [Ss]pot',\n    background: '[Aa]ftground',\n    given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n    // Also aliasing Pirate verbs for given-when-then for signature-lookup\n    get giveth() {\n      return this.given;\n    },\n    get whence() {\n      return this.when;\n    },\n    get thence() {\n      return this.then;\n    },\n  };\n\n  return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n    scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n    examples: '[Pp]rzykłady',\n    pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n    only: '[Tt]ylko',\n    background: '[Zz]ałożenia',\n    given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n    when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n    then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n    _steps: ['given', 'when', 'then', 'zakladajac', 'majac', 'jezeli', 'jesli', 'gdy', 'kiedy', 'wtedy'],\n    // Also aliasing Polish verbs for given-when-then for signature-lookup\n    get zakladajac() {\n      return this.given;\n    },\n    get majac() {\n      return this.given;\n    },\n    get jezeli() {\n      return this.when;\n    },\n    get jesli() {\n      return this.when;\n    },\n    get gdy() {\n      return this.when;\n    },\n    get kiedy() {\n      return this.when;\n    },\n    get wtedy() {\n      return this.then;\n    },\n  };\n\n  return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n    scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n    examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n    pending: '[Pp]endente',\n    only: '[S][óo]',\n    background: '[Ff]undo',\n    given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n    when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n    then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n    _steps: ['given', 'when', 'then', 'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas', 'quando', 'se', 'entao'],\n\n    get seja() {\n      return this.given;\n    },\n    get sejam() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get quando() {\n      return this.when;\n    },\n    get se() {\n      return this.when;\n    },\n    get entao() {\n      return this.then;\n    },\n  };\n\n  return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n    scenario: 'Сценарий',\n    examples: 'Примеры?',\n    pending: '(?:[Ww]ip|[Tt]odo)',\n    only: 'Только',\n    background: '(?:[Пп]редыстория|[Кк]онтекст)',\n    given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n    scenario: '(?:[Ee]scenario|[Cc]aso)',\n    examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n    pending: '[Pp]endiente',\n    only: '[S]ólo',\n    background: '[Ff]ondo',\n    given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n    when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n    then: '(?:[Ee]ntonces)',\n\n    _steps: ['given', 'when', 'then', 'sea', 'sean', 'dado', 'dada', 'dados', 'dadas', 'cuando', 'si', 'entonces'],\n\n    get sea() {\n      return this.given;\n    },\n    get sean() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get cuando() {\n      return this.when;\n    },\n    get si() {\n      return this.when;\n    },\n    get entonces() {\n      return this.then;\n    },\n  };\n\n  return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n    scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n    examples: '[Пп]риклади',\n    pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n    only: '[Тт]ільки',\n    background: '[Кк]онтекст',\n    given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n    when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n    then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  Chinese: require('./Chinese'),\n  English: require('./English'),\n  French: require('./French'),\n  German: require('./German'),\n  Dutch: require('./Dutch'),\n  Norwegian: require('./Norwegian'),\n  Pirate: require('./Pirate'),\n  Ukrainian: require('./Ukrainian'),\n  Polish: require('./Polish'),\n  Spanish: require('./Spanish'),\n  Russian: require('./Russian'),\n  Portuguese: require('./Portuguese'),\n  default: require('./English'),\n  Language: require('./Language'),\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n'use strict';\n\nvar FeatureFileParser = function (options) {\n  var fs = require('../shims').fs;\n  var FeatureParser = require('./FeatureParser');\n  var parser = new FeatureParser(options);\n\n  this.parse = function (file, next) {\n    var text = fs.readFileSync(file, 'utf8');\n    var feature = parser.parse(text);\n    return (next && next(feature)) || feature;\n  };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function (options) {\n  /* eslint-disable no-redeclare */\n  var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']' };\n  var options = options && options.is_language ? { language: options } : options || defaults;\n  var language = options.language || defaults.language;\n  var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n  var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n  /* eslint-enable no-redeclare */\n\n  var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n  var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n  var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n  var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n  var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n  var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n  var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n  var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n  var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n  var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n  var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n  var specification;\n  var comment;\n\n  this.parse = function (text, next) {\n    reset();\n    split(text).each(parse_line);\n    return (next && next(specification.export())) || specification.export();\n  };\n\n  function reset() {\n    specification = new Specification();\n    comment = false;\n  }\n\n  function split(text) {\n    return $(text.split(/\\r\\n|\\n/));\n  }\n\n  function parse_line(line, index) {\n    var match;\n    var line_number = index + 1;\n    try {\n      // eslint-disable-next-line no-return-assign\n      if ((match = MULTI_LINE_COMMENT_REGEX.test(line))) return (comment = !comment);\n      if (comment) return;\n      if ((match = SINGLE_LINE_COMMENT_REGEX.test(line))) return;\n      if ((match = SIMPLE_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n      if ((match = NVP_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n      if ((match = FEATURE_REGEX.exec(line))) return specification.handle('Feature', match[1], line_number);\n      if ((match = SCENARIO_REGEX.exec(line))) return specification.handle('Scenario', match[1], line_number);\n      if ((match = BACKGROUND_REGEX.exec(line))) return specification.handle('Background', match[1], line_number);\n      if ((match = EXAMPLES_REGEX.exec(line))) return specification.handle('Examples', line_number);\n      if ((match = BLANK_REGEX.exec(line))) return specification.handle('Blank', match[0], line_number);\n      if ((match = DASH_REGEX.exec(line))) return specification.handle('Dash', match[1], line_number);\n      if ((match = TEXT_REGEX.exec(line))) return specification.handle('Text', match[1], line_number);\n    } catch (e) {\n      e.message = 'Error parsing line ' + line_number + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n      throw e;\n    }\n  }\n\n  var Handlers = function (handlers) {\n    // eslint-disable-next-line no-redeclare\n    var handlers = handlers || {};\n\n    this.register = function (event, handler) {\n      handlers[event] = handler;\n    };\n\n    this.unregister = function () {\n      $(Array.prototype.slice.call(arguments)).each(function (event) {\n        delete handlers[event];\n      });\n    };\n\n    this.find = function (event) {\n      if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n      return { handle: handlers[event.toLowerCase()] };\n    };\n  };\n\n  var Specification = function () {\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      text: fn.noop,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      feature: start_feature,\n      scenario: start_scenario,\n      background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n      // eslint-disable-next-line no-return-assign\n      return (feature = new Feature(title, annotations, new Annotations()));\n    }\n\n    function start_scenario(event, title, line_number) {\n      feature = new Feature(title, new Annotations(), annotations);\n      return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function (event, data, line_number) {\n      current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      if (!feature) throw new Error('A feature must contain one or more scenarios');\n      return feature.export();\n    };\n  };\n\n  var Annotations = function () {\n    var annotations = {};\n\n    this.stash = function (key, value) {\n      if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n      annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function () {\n      return annotations;\n    };\n  };\n\n  var Feature = function (title, annotations, stashed_annotations) {\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n      text: capture_description,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n      background: start_background,\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n      background = new Background(title, _this);\n      stashed_annotations = new Annotations();\n      return background;\n    }\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background', 'text');\n      stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n      description.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, title) {\n      var scenario = new Scenario(title, background, stashed_annotations, _this);\n      scenarios.push(scenario);\n      stashed_annotations = new Annotations();\n      return scenario;\n    }\n\n    function validate() {\n      if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        scenarios: $(scenarios)\n          .collect(function (scenario) {\n            return scenario.export();\n          })\n          .flatten()\n          .naked(),\n      };\n    };\n  };\n\n  var Background = function (title, feature) {\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n    });\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', stash_annotation);\n      handlers.register('scenario', start_scenario);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      validate();\n      return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        steps: steps,\n      };\n    };\n  };\n\n  var NullBackground = function () {\n    var handlers = new Handlers();\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      return {\n        steps: [],\n      };\n    };\n  };\n\n  var Scenario = function (title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: start_scenario,\n      scenario: start_scenario,\n      examples: start_examples,\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n      handlers.register('examples', start_examples);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n      validate();\n      examples = new Examples(_this);\n      return examples;\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      var result = {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        steps: background.export().steps.concat(steps),\n      };\n      return examples ? examples.expand(result) : result;\n    };\n  };\n\n  var Examples = function (scenario) {\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      blank: fn.noop,\n      dash: start_example_table,\n      text: capture_headings,\n    });\n\n    function start_example_table(evnet, data, line_number) {\n      handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n      handlers.register('annotation', stash_annotation);\n      handlers.register('text', capture_singleline_fields);\n      handlers.register('dash', enable_multiline_examples);\n      var pos = 1;\n      headings = split(data)\n        .collect(function (column) {\n          var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n          pos += column.length + 1;\n          return attributes;\n        })\n        .naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      handlers.unregister('blank', 'dash');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n      handlers.register('dash', end_example_table);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n      annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', continue_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n      parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n      handlers.unregister('text', 'dash');\n      handlers.register('blank', fn.noop);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n      var fields = examples.last().fields;\n      $(headings).each(function (heading) {\n        fields[heading.text + '.index'] = [examples.length];\n        fields[heading.text + '.start.line'] = [line_number];\n        fields[heading.text + '.start.column'] = [heading.left + heading.indentation];\n      });\n    }\n\n    function parse_fields(row, fields) {\n      split(row, headings.length).each(function (field, index) {\n        var column = headings[index].text;\n        var indentation = headings[index].indentation;\n        var text = StringUtils.rtrim(field.substr(indentation));\n        if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n        fields[column] = (fields[column] || []).concat(text);\n      });\n      return fields;\n    }\n\n    function split(row, number_of_fields) {\n      var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n      var fields = $(row.split(separator));\n      if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n        throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n      }\n      return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n      if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function (scenario) {\n      validate();\n      return examples\n        .collect(function (example) {\n          return {\n            title: substitute(example.fields, scenario.title),\n            annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n            description: substitute_all(example, scenario.description),\n            steps: substitute_all(example.fields, scenario.steps),\n          };\n        })\n        .naked();\n    };\n\n    function shallow_merge() {\n      var result = {};\n      $(Array.prototype.slice.call(arguments)).each(function (annotations) {\n        for (var key in annotations) {\n          result[key] = annotations[key];\n        }\n      });\n      return result;\n    }\n\n    function substitute_all(example, lines) {\n      return $(lines)\n        .collect(function (line) {\n          return substitute(example, line);\n        })\n        .naked();\n    }\n\n    function substitute(example, line) {\n      for (var heading in example) {\n        line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n      }\n      return line;\n    }\n  };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\n\nvar StepParser = function () {\n  var NON_BLANK_REGEX = /[^\\s]/;\n\n  this.parse = function (text, next) {\n    var steps = split(text).find_all(non_blanks);\n    return (next && next(steps)) || steps;\n  };\n\n  var split = function (text) {\n    return $(text.split(/\\n/));\n  };\n\n  var non_blanks = function (text) {\n    return text && NON_BLANK_REGEX.test(text);\n  };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  StepParser: require('./StepParser'),\n  FeatureParser: require('./FeatureParser'),\n  FeatureFileParser: require('./FeatureFileParser'),\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){(function (){\n'use strict';\n\nif (!module.client) {\n  var fs = require('../shims').fs;\n  global.process = global.process || {\n    cwd: function () {\n      return fs.workingDirectory;\n    },\n  };\n}\n\nmodule.exports = function (yadda, casper) {\n  var EventBus = require('yadda').EventBus;\n\n  yadda.interpreter.interpret_step = function (step, ctx, next) {\n    var _this = this;\n    casper.then(function () {\n      casper.test.info(step);\n      EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n      _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    });\n  };\n\n  casper.yadda = function (script, ctx) {\n    if (script === undefined) return this;\n    yadda.run(script, ctx);\n  };\n};\n\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  casper: require('./CasperPlugin'),\n  mocha: {\n    ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n    StepLevelPlugin: require('./mocha/StepLevelPlugin'),\n  },\n  get jasmine() {\n    return this.mocha;\n  },\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n'use strict';\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function (options) {\n  /* jslint shadow: true */\n  var platform = new Platform();\n  var language = options.language || Localisation.default;\n  var parser = options.parser || new FeatureFileParser(language);\n  var container = options.container || platform.get_container();\n\n  function featureFiles(files, iterator) {\n    $(files).each(function (file) {\n      features(parser.parse(file), iterator);\n    });\n  }\n\n  function features(features, iterator) {\n    $(features).each(function (feature) {\n      describe(feature.title, feature, iterator);\n    });\n  }\n\n  function describe(title, subject, iterator) {\n    var _describe = getDescribe(subject.annotations);\n    _describe(title, function () {\n      iterator(subject);\n    });\n  }\n\n  function it_async(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function (done) {\n      iterator(this, subject, done);\n    });\n  }\n\n  function it_sync(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function () {\n      iterator(this, subject);\n    });\n  }\n\n  function getIt(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xit;\n    if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n    return container.it;\n  }\n\n  function getDescribe(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xdescribe;\n    if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n    return container.describe;\n  }\n\n  function has_annotation(annotations, name) {\n    var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n    for (var key in annotations) {\n      if (regexp.test(key)) return true;\n    }\n  }\n\n  return {\n    featureFiles: featureFiles,\n    features: features,\n    describe: describe,\n    it_async: it_async,\n    it_sync: it_sync,\n  };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n      itFn(scenario.title, scenario, function (context, scenario, done) {\n        iterator(scenario, done);\n      });\n    });\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      base_plugin.describe(scenario.title, scenario, iterator);\n    });\n  }\n\n  function steps(steps, iterator) {\n    var abort = false;\n\n    $(steps).each(function (step) {\n      var stepFn = iterator.length === 1 ? step_sync : step_async;\n      stepFn(step, iterator);\n    });\n\n    function step_async(step, iterator) {\n      base_plugin.it_async(step, step, function (context, step, done) {\n        if (abort) {\n          return context.skip ? context.skip() : done();\n        }\n        abort = true;\n        iterator.bind(context)(step, function (err) {\n          if (err) return (done.fail || done)(err);\n          abort = false;\n          done();\n        });\n      });\n    }\n\n    function step_sync(step, iterator) {\n      base_plugin.it_sync(step, step, function (context, step) {\n        if (abort) return context.skip && context.skip();\n        abort = true;\n        iterator.bind(context)(step);\n        abort = false;\n      });\n    }\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n  container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n'use strict';\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function (s1, s2) {\n  this.value;\n  this.type = 'LevenshteinDistanceScore';\n  var distance_table;\n  var _this = this;\n\n  var initialise = function () {\n    var x = s1.length;\n    var y = s2.length;\n\n    distance_table = new Array(x + 1);\n\n    /* eslint-disable no-redeclare */\n    for (var i = 0; i <= x; i++) {\n      distance_table[i] = new Array(y + 1);\n    }\n\n    for (var i = 0; i <= x; i++) {\n      for (var j = 0; j <= y; j++) {\n        distance_table[i][j] = 0;\n      }\n    }\n\n    for (var i = 0; i <= x; i++) {\n      distance_table[i][0] = i;\n    }\n\n    for (var j = 0; j <= y; j++) {\n      distance_table[0][j] = j;\n    }\n    /* eslint-enable no-redeclare */\n  };\n\n  var score = function () {\n    // eslint-disable-next-line no-return-assign\n    if (s1 === s2) return (_this.value = 0);\n\n    for (var j = 0; j < s2.length; j++) {\n      for (var i = 0; i < s1.length; i++) {\n        if (s1[i] === s2[j]) {\n          distance_table[i + 1][j + 1] = distance_table[i][j];\n        } else {\n          var deletion = distance_table[i][j + 1] + 1;\n          var insertion = distance_table[i + 1][j] + 1;\n          var substitution = distance_table[i][j] + 1;\n          distance_table[i + 1][j + 1] = Math.min(substitution, deletion, insertion);\n        }\n      }\n    }\n    _this.value = distance_table[s1.length][s2.length];\n  };\n\n  this.compare = function (other) {\n    return other.value - this.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n\n  initialise();\n  score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\n\nvar MultiScore = function (scores) {\n  this.scores = $(scores);\n  this.type = 'MultiScore';\n\n  this.compare = function (other) {\n    for (var i = 0; i < this.scores.length; i++) {\n      var difference = this.scores[i].compare(other.scores[i]);\n      if (difference) return difference;\n    }\n    return 0;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    if (this.type !== other.type) return false;\n    return this.compare(other) === 0;\n  };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n'use strict';\n\nvar SameLibraryScore = function (m1, m2) {\n  this.value = m1.is_sibling(m2) ? 1 : 0;\n  this.type = 'SameLibraryScore';\n\n  this.compare = function (other) {\n    return this.value - other.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){(function (){\n'use strict';\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n  var platform = new Platform();\n\n  var shims = {\n    node: function () {\n      return {\n        fs: require('fs'),\n        path: require('path'),\n        process: process,\n      };\n    },\n    phantom: function () {\n      return {\n        fs: require('./phantom-fs'),\n        path: require('./phantom-path'),\n        process: require('./phantom-process'),\n      };\n    },\n    karma: function () {\n      return {\n        fs: require('./karma-fs'),\n        path: require('./karma-path'),\n        process: require('./karma-process'),\n      };\n    },\n  };\n\n  function get_shim() {\n    if (platform.is_phantom()) return shims.phantom();\n    if (platform.is_browser() && platform.is_karma()) return shims.karma();\n    if (platform.is_node()) return shims.node();\n    return {};\n  }\n\n  return get_shim();\n})();\n\n}).call(this)}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var path = require('./karma-path');\n\n  function absolutePath(relativePath) {\n    return path.resolve(path.normalize(relativePath.split('\\\\').join('/')));\n  }\n\n  var KarmaFileSystem = function () {\n    this.registry = new KarmaPathRegistry();\n    this.converter = new KarmaUriPathConverter('/base/', '/');\n    this.reader = new KarmaFileReader(this.converter);\n\n    var servedUris = Object.keys(window.__karma__.files);\n    var servedFiles = this.converter.parseUris(servedUris);\n    servedFiles.forEach(this.registry.addFile, this.registry);\n  };\n  KarmaFileSystem.prototype = {\n    constructor: KarmaFileSystem,\n    workingDirectory: '/',\n    existsSync: function (path) {\n      return this.registry.exists(path);\n    },\n    readdirSync: function (path) {\n      return this.registry.getContent(path);\n    },\n    statSync: function (path) {\n      return {\n        isDirectory: function () {\n          return this.registry.isDirectory(path);\n        }.bind(this),\n      };\n    },\n    readFileSync: function (file, encoding) {\n      if (encoding !== 'utf8') throw new Error('This fs.readFileSync() shim does not support other than utf8 encoding.');\n      if (!this.registry.isFile(file)) throw new Error('File does not exist: ' + file);\n      return this.reader.readFile(file);\n    },\n  };\n\n  var KarmaPathRegistry = function KarmaPathRegistry() {\n    this.paths = {};\n  };\n\n  KarmaPathRegistry.prototype = {\n    constructor: KarmaPathRegistry,\n    addFile: function (file) {\n      file = absolutePath(file);\n      this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n      var parentDirectory = path.dirname(file);\n      this.addDirectory(parentDirectory);\n    },\n    addDirectory: function (directory) {\n      directory = absolutePath(directory);\n      this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n      var parentDirectory = path.dirname(directory);\n      if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n    },\n    isFile: function (file) {\n      file = absolutePath(file);\n      return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n    },\n    isDirectory: function (directory) {\n      directory = absolutePath(directory);\n      return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n    },\n    exists: function (node) {\n      node = absolutePath(node);\n      return this.paths.hasOwnProperty(node);\n    },\n    getContent: function (directory) {\n      if (!this.isDirectory(directory)) throw new Error('Not a directory: ' + directory);\n      directory = absolutePath(directory);\n      return Object.keys(this.paths)\n        .filter(function (node) {\n          if (node === directory) return false;\n          var parentDirectory = path.dirname(node);\n          return parentDirectory === directory;\n        }, this)\n        .map(function (node) {\n          return path.basename(node);\n        });\n    },\n  };\n\n  KarmaPathRegistry.TYPE_FILE = 0;\n  KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n  var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n    this.workingDirectory = workingDirectory;\n    this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n    this.baseUri = baseUri;\n    this.baseUriPattern = this.patternFromBase(baseUri);\n  };\n\n  KarmaUriPathConverter.prototype = {\n    constructor: KarmaUriPathConverter,\n    patternFromBase: function (string, flags) {\n      var pattern = '^' + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n      return new RegExp(pattern, flags);\n    },\n    parseUris: function (uris) {\n      return uris\n        .filter(function (uri) {\n          return this.baseUriPattern.test(uri);\n        }, this)\n        .map(function (uri) {\n          return uri.replace(this.baseUriPattern, this.workingDirectory);\n        }, this);\n    },\n    buildUri: function (file) {\n      file = absolutePath(file);\n      if (!this.workingDirectoryPattern.test(file)) throw new Error('Path is not in working directory: ' + file);\n      return file.replace(this.workingDirectoryPattern, this.baseUri);\n    },\n  };\n\n  var KarmaFileReader = function KarmaFileReader(converter) {\n    this.converter = converter;\n  };\n\n  KarmaFileReader.prototype = {\n    constructor: KarmaFileReader,\n    readFile: function (file) {\n      var uri = this.converter.buildUri(file);\n      // eslint-disable-next-line no-undef\n      var xhr = new XMLHttpRequest();\n      xhr.open('get', uri, false);\n      xhr.send();\n      return xhr.responseText;\n    },\n  };\n\n  return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n  }\n\n  if (typeof path.normalize !== 'function' || typeof path.dirname !== 'function') throw new Error('The path module emulation does not contain implementations of required functions.');\n\n  return path;\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var fs = require('./karma-fs');\n  var process = {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n\n  fs.existsSync = fs.existsSync || fs.exists;\n\n  fs.readdirSync =\n    fs.readdirSync ||\n    function (path) {\n      return fs.list(path).filter(function (name) {\n        return name !== '.' && name !== '..';\n      });\n    };\n\n  fs.statSync =\n    fs.statSync ||\n    function (path) {\n      return {\n        isDirectory: function () {\n          return fs.isDirectory(path);\n        },\n      };\n    };\n\n  return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    // meh\n  }\n\n  path.join =\n    path.join ||\n    function () {\n      return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n  path.relative =\n    path.relative ||\n    function (from, to) {\n      return from + fs.separator + to;\n    };\n\n  return path;\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var process = typeof process !== 'undefined' ? process : {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){(function (){\n// 'path' module extracted from Node.js v8.11.1 (only the posix part)\n// transplited with Babel\n\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nfunction assertPath(path) {\n  if (typeof path !== 'string') {\n    throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));\n  }\n}\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeStringPosix(path, allowAboveRoot) {\n  var res = '';\n  var lastSegmentLength = 0;\n  var lastSlash = -1;\n  var dots = 0;\n  var code;\n  for (var i = 0; i <= path.length; ++i) {\n    if (i < path.length)\n      code = path.charCodeAt(i);\n    else if (code === 47 /*/*/)\n      break;\n    else\n      code = 47 /*/*/;\n    if (code === 47 /*/*/) {\n      if (lastSlash === i - 1 || dots === 1) {\n        // NOOP\n      } else if (lastSlash !== i - 1 && dots === 2) {\n        if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {\n          if (res.length > 2) {\n            var lastSlashIndex = res.lastIndexOf('/');\n            if (lastSlashIndex !== res.length - 1) {\n              if (lastSlashIndex === -1) {\n                res = '';\n                lastSegmentLength = 0;\n              } else {\n                res = res.slice(0, lastSlashIndex);\n                lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n              }\n              lastSlash = i;\n              dots = 0;\n              continue;\n            }\n          } else if (res.length === 2 || res.length === 1) {\n            res = '';\n            lastSegmentLength = 0;\n            lastSlash = i;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          if (res.length > 0)\n            res += '/..';\n          else\n            res = '..';\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0)\n          res += '/' + path.slice(lastSlash + 1, i);\n        else\n          res = path.slice(lastSlash + 1, i);\n        lastSegmentLength = i - lastSlash - 1;\n      }\n      lastSlash = i;\n      dots = 0;\n    } else if (code === 46 /*.*/ && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\n\nfunction _format(sep, pathObject) {\n  var dir = pathObject.dir || pathObject.root;\n  var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');\n  if (!dir) {\n    return base;\n  }\n  if (dir === pathObject.root) {\n    return dir + base;\n  }\n  return dir + sep + base;\n}\n\nvar posix = {\n  // path.resolve([from ...], to)\n  resolve: function resolve() {\n    var resolvedPath = '';\n    var resolvedAbsolute = false;\n    var cwd;\n\n    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n      var path;\n      if (i >= 0)\n        path = arguments[i];\n      else {\n        if (cwd === undefined)\n          cwd = process.cwd();\n        path = cwd;\n      }\n\n      assertPath(path);\n\n      // Skip empty entries\n      if (path.length === 0) {\n        continue;\n      }\n\n      resolvedPath = path + '/' + resolvedPath;\n      resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    }\n\n    // At this point the path should be resolved to a full absolute path, but\n    // handle relative paths to be safe (might happen when process.cwd() fails)\n\n    // Normalize the path\n    resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);\n\n    if (resolvedAbsolute) {\n      if (resolvedPath.length > 0)\n        return '/' + resolvedPath;\n      else\n        return '/';\n    } else if (resolvedPath.length > 0) {\n      return resolvedPath;\n    } else {\n      return '.';\n    }\n  },\n\n  normalize: function normalize(path) {\n    assertPath(path);\n\n    if (path.length === 0) return '.';\n\n    var isAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;\n\n    // Normalize the path\n    path = normalizeStringPosix(path, !isAbsolute);\n\n    if (path.length === 0 && !isAbsolute) path = '.';\n    if (path.length > 0 && trailingSeparator) path += '/';\n\n    if (isAbsolute) return '/' + path;\n    return path;\n  },\n\n  isAbsolute: function isAbsolute(path) {\n    assertPath(path);\n    return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;\n  },\n\n  join: function join() {\n    if (arguments.length === 0)\n      return '.';\n    var joined;\n    for (var i = 0; i < arguments.length; ++i) {\n      var arg = arguments[i];\n      assertPath(arg);\n      if (arg.length > 0) {\n        if (joined === undefined)\n          joined = arg;\n        else\n          joined += '/' + arg;\n      }\n    }\n    if (joined === undefined)\n      return '.';\n    return posix.normalize(joined);\n  },\n\n  relative: function relative(from, to) {\n    assertPath(from);\n    assertPath(to);\n\n    if (from === to) return '';\n\n    from = posix.resolve(from);\n    to = posix.resolve(to);\n\n    if (from === to) return '';\n\n    // Trim any leading backslashes\n    var fromStart = 1;\n    for (; fromStart < from.length; ++fromStart) {\n      if (from.charCodeAt(fromStart) !== 47 /*/*/)\n        break;\n    }\n    var fromEnd = from.length;\n    var fromLen = fromEnd - fromStart;\n\n    // Trim any leading backslashes\n    var toStart = 1;\n    for (; toStart < to.length; ++toStart) {\n      if (to.charCodeAt(toStart) !== 47 /*/*/)\n        break;\n    }\n    var toEnd = to.length;\n    var toLen = toEnd - toStart;\n\n    // Compare paths to find the longest common path from root\n    var length = fromLen < toLen ? fromLen : toLen;\n    var lastCommonSep = -1;\n    var i = 0;\n    for (; i <= length; ++i) {\n      if (i === length) {\n        if (toLen > length) {\n          if (to.charCodeAt(toStart + i) === 47 /*/*/) {\n            // We get here if `from` is the exact base path for `to`.\n            // For example: from='/foo/bar'; to='/foo/bar/baz'\n            return to.slice(toStart + i + 1);\n          } else if (i === 0) {\n            // We get here if `from` is the root\n            // For example: from='/'; to='/foo'\n            return to.slice(toStart + i);\n          }\n        } else if (fromLen > length) {\n          if (from.charCodeAt(fromStart + i) === 47 /*/*/) {\n            // We get here if `to` is the exact base path for `from`.\n            // For example: from='/foo/bar/baz'; to='/foo/bar'\n            lastCommonSep = i;\n          } else if (i === 0) {\n            // We get here if `to` is the root.\n            // For example: from='/foo'; to='/'\n            lastCommonSep = 0;\n          }\n        }\n        break;\n      }\n      var fromCode = from.charCodeAt(fromStart + i);\n      var toCode = to.charCodeAt(toStart + i);\n      if (fromCode !== toCode)\n        break;\n      else if (fromCode === 47 /*/*/)\n        lastCommonSep = i;\n    }\n\n    var out = '';\n    // Generate the relative path based on the path difference between `to`\n    // and `from`\n    for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n      if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {\n        if (out.length === 0)\n          out += '..';\n        else\n          out += '/..';\n      }\n    }\n\n    // Lastly, append the rest of the destination (`to`) path that comes after\n    // the common path parts\n    if (out.length > 0)\n      return out + to.slice(toStart + lastCommonSep);\n    else {\n      toStart += lastCommonSep;\n      if (to.charCodeAt(toStart) === 47 /*/*/)\n        ++toStart;\n      return to.slice(toStart);\n    }\n  },\n\n  _makeLong: function _makeLong(path) {\n    return path;\n  },\n\n  dirname: function dirname(path) {\n    assertPath(path);\n    if (path.length === 0) return '.';\n    var code = path.charCodeAt(0);\n    var hasRoot = code === 47 /*/*/;\n    var end = -1;\n    var matchedSlash = true;\n    for (var i = path.length - 1; i >= 1; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          if (!matchedSlash) {\n            end = i;\n            break;\n          }\n        } else {\n        // We saw the first non-path separator\n        matchedSlash = false;\n      }\n    }\n\n    if (end === -1) return hasRoot ? '/' : '.';\n    if (hasRoot && end === 1) return '//';\n    return path.slice(0, end);\n  },\n\n  basename: function basename(path, ext) {\n    if (ext !== undefined && typeof ext !== 'string') throw new TypeError('\"ext\" argument must be a string');\n    assertPath(path);\n\n    var start = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i;\n\n    if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n      if (ext.length === path.length && ext === path) return '';\n      var extIdx = ext.length - 1;\n      var firstNonSlashEnd = -1;\n      for (i = path.length - 1; i >= 0; --i) {\n        var code = path.charCodeAt(i);\n        if (code === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else {\n          if (firstNonSlashEnd === -1) {\n            // We saw the first non-path separator, remember this index in case\n            // we need it if the extension ends up not matching\n            matchedSlash = false;\n            firstNonSlashEnd = i + 1;\n          }\n          if (extIdx >= 0) {\n            // Try to match the explicit extension\n            if (code === ext.charCodeAt(extIdx)) {\n              if (--extIdx === -1) {\n                // We matched the extension, so mark this as the end of our path\n                // component\n                end = i;\n              }\n            } else {\n              // Extension does not match, so our result is the entire path\n              // component\n              extIdx = -1;\n              end = firstNonSlashEnd;\n            }\n          }\n        }\n      }\n\n      if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;\n      return path.slice(start, end);\n    } else {\n      for (i = path.length - 1; i >= 0; --i) {\n        if (path.charCodeAt(i) === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else if (end === -1) {\n          // We saw the first non-path separator, mark this as the end of our\n          // path component\n          matchedSlash = false;\n          end = i + 1;\n        }\n      }\n\n      if (end === -1) return '';\n      return path.slice(start, end);\n    }\n  },\n\n  extname: function extname(path) {\n    assertPath(path);\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n    for (var i = path.length - 1; i >= 0; --i) {\n      var code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1)\n            startDot = i;\n          else if (preDotState !== 1)\n            preDotState = 1;\n      } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n        // We saw a non-dot character immediately before the dot\n        preDotState === 0 ||\n        // The (right-most) trimmed path component is exactly '..'\n        preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      return '';\n    }\n    return path.slice(startDot, end);\n  },\n\n  format: function format(pathObject) {\n    if (pathObject === null || typeof pathObject !== 'object') {\n      throw new TypeError('The \"pathObject\" argument must be of type Object. Received type ' + typeof pathObject);\n    }\n    return _format('/', pathObject);\n  },\n\n  parse: function parse(path) {\n    assertPath(path);\n\n    var ret = { root: '', dir: '', base: '', ext: '', name: '' };\n    if (path.length === 0) return ret;\n    var code = path.charCodeAt(0);\n    var isAbsolute = code === 47 /*/*/;\n    var start;\n    if (isAbsolute) {\n      ret.root = '/';\n      start = 1;\n    } else {\n      start = 0;\n    }\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i = path.length - 1;\n\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n\n    // Get non-dir info\n    for (; i >= start; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;\n        } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n    // We saw a non-dot character immediately before the dot\n    preDotState === 0 ||\n    // The (right-most) trimmed path component is exactly '..'\n    preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      if (end !== -1) {\n        if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);\n      }\n    } else {\n      if (startPart === 0 && isAbsolute) {\n        ret.name = path.slice(1, startDot);\n        ret.base = path.slice(1, end);\n      } else {\n        ret.name = path.slice(startPart, startDot);\n        ret.base = path.slice(startPart, end);\n      }\n      ret.ext = path.slice(startDot, end);\n    }\n\n    if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';\n\n    return ret;\n  },\n\n  sep: '/',\n  delimiter: ':',\n  win32: null,\n  posix: null\n};\n\nposix.posix = posix;\n\nmodule.exports = posix;\n\n}).call(this)}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n'use strict';\n\nvar api = {\n  Yadda: require('./Yadda'),\n  EventBus: require('./EventBus'),\n  Interpreter: require('./Interpreter'),\n  Context: require('./Context'),\n  Library: require('./Library'),\n  Dictionary: require('./Dictionary'),\n  FeatureFileSearch: require('./FeatureFileSearch'),\n  FileSearch: require('./FileSearch'),\n  Platform: require('./Platform'),\n  localisation: require('./localisation/index'),\n  converters: require('./converters/index'),\n  parsers: require('./parsers/index'),\n  plugins: require('./plugins/index'),\n  shims: require('./shims/index'),\n  createInstance: function () {\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n  },\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-2.2.0.js",
    "content": "require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\n'use strict';\n\nvar fn = require('./fn');\n\nmodule.exports = function (obj) {\n  function ensure_array(obj) {\n    var array = obj ? [].concat(obj) : [];\n    array.in_array = fn.curry(array, in_array, array);\n    array.each = fn.curry(array, each, array);\n    array.each_async = fn.curry(array, each_async, array);\n    array.collect = fn.curry(array, collect, array);\n    array.collect_async = fn.curry(array, collect_async, array);\n    array.flatten = fn.curry(array, flatten, array);\n    array.inject = fn.curry(array, inject, array);\n    array.push_all = fn.curry(array, push_all, array);\n    array.fill = fn.curry(array, fill, array);\n    array.find_all = fn.curry(array, find_all, array);\n    array.find = fn.curry(array, find, array);\n    array.last = fn.curry(array, last, array);\n    array.naked = fn.curry(array, naked, array);\n    return array;\n  }\n\n  function is_array(obj) {\n    return Object.prototype.toString.call(obj) === '[object Array]';\n  }\n\n  function in_array(items, item) {\n    for (var i = 0; i < items.length; i++) {\n      if (items[i] === item) {\n        return true;\n      }\n    }\n  }\n\n  function flatten(items) {\n    if (!is_array(items)) return [items];\n    if (items.length === 0) return items;\n    var head = flatten(items[0]);\n    var tail = flatten(items.slice(1));\n    return ensure_array(head.concat(tail));\n  }\n\n  function each(items, iterator) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(items[i], i);\n    }\n    return result;\n  }\n\n  function each_async(items, iterator, callback) {\n    callback = callback || fn.noop;\n    if (!items.length) return callback();\n    var index = 0;\n    var iterate = function () {\n      iterator(items[index], index, function (err, result) {\n        if (err) return callback(err);\n        if (++index >= items.length) return callback(null, result);\n        iterate();\n      });\n    };\n    iterate();\n  }\n\n  function collect(items, iterator) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      results.push(iterator(items[i], i));\n    }\n    return results;\n  }\n\n  function collect_async(items, iterator, callback) {\n    var results = ensure_array();\n    each_async(\n      items,\n      function (item, index, each_callback) {\n        iterator(item, index, function (err) {\n          if (err) return each_callback(err);\n          results.push_all(Array.prototype.splice.call(arguments, 1));\n          each_callback();\n        });\n      },\n      function (err) {\n        if (err) return callback(err);\n        callback(null, results);\n      }\n    );\n  }\n\n  function inject(items, default_value, iterator) {\n    var result = default_value;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(result, items[i]);\n    }\n    return result;\n  }\n\n  function push_all(items, more_items) {\n    more_items = more_items ? [].concat(more_items) : [];\n    for (var i = 0; i < more_items.length; i++) {\n      items.push(more_items[i]);\n    }\n    return items;\n  }\n\n  function fill(items, item, num) {\n    for (var i = 0; i < num; i++) {\n      items.push(item);\n    }\n    return items;\n  }\n\n  function find_all(items, test) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        results.push(items[i]);\n      }\n    }\n    return results;\n  }\n\n  function find(items, test) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        result = items[i];\n        break;\n      }\n    }\n    return result;\n  }\n\n  function last(items) {\n    return items[items.length - 1];\n  }\n\n  function naked(items) {\n    return [].concat(items);\n  }\n\n  return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n'use strict';\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function (step, macros, last_macro) {\n  var results = [];\n\n  this.validate = function () {\n    if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n    if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n    return { step: step, valid: true, winner: this.winner() };\n  };\n\n  this.clear_winner = function () {\n    if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n    if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n    return this.winner();\n  };\n\n  function is_undefined() {\n    return results.length === 0;\n  }\n\n  function is_ambiguous() {\n    return results.length > 1 && results[0].score.equals(results[1].score);\n  }\n\n  this.winner = function () {\n    return results[0].macro;\n  };\n\n  function winning_patterns() {\n    return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n  }\n\n  function rank(step, macros) {\n    results = macros\n      .collect(function (macro) {\n        return {\n          macro: macro,\n          score: new MultiScore([new LevenshteinDistanceScore(step, macro.levenshtein_signature()), new SameLibraryScore(macro, last_macro)]),\n        };\n      })\n      .sort(by_ascending_score);\n  }\n\n  function by_ascending_score(a, b) {\n    return b.score.compare(a.score);\n  }\n\n  function by_winning_score(result) {\n    return result.score.equals(results[0].score);\n  }\n\n  function macro_signatures(result) {\n    return result.macro.toString();\n  }\n\n  rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n'use strict';\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function (properties) {\n  // I was previously getting some weird errors using instanceof to determine if\n  // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n  this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n  this.properties = {};\n\n  this.merge = function (other) {\n    if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n    return new Context(this.properties)._merge(other);\n  };\n\n  this._merge = function (other) {\n    for (var key in other) {\n      this.properties[key] = other[key];\n    }\n    return this;\n  };\n\n  this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function (prefix) {\n  // eslint-disable-next-line no-redeclare\n  var prefix = prefix || '$';\n  var definitions = {};\n  var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n  var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n  var _this = this;\n\n  this.define = function (term, pattern, converters) {\n    if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n    if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n    if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n    if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n    definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n    return this;\n  };\n\n  this.merge = function (other) {\n    if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n    return new Dictionary(prefix)._merge(this)._merge(other);\n  };\n\n  this._merge = function (other) {\n    other.each(function (term, definition) {\n      _this.define(term, definition.pattern);\n    });\n    return this;\n  };\n\n  this._prefix = function () {\n    return prefix;\n  };\n\n  this.each = function (callback) {\n    for (var term in definitions) {\n      callback(term, definitions[term]);\n    }\n  };\n\n  this.expand = function (signature, already_expanding) {\n    var text = normalise(signature);\n    return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) } : { pattern: text, converters: get_converters(text) };\n  };\n\n  function expand_sub_terms(text, already_expanding) {\n    return get_sub_terms(text).each(function (sub_term) {\n      if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n      var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n      text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n      return text;\n    });\n  }\n\n  function get_sub_terms(text) {\n    return term_grouping_pattern.groups(text);\n  }\n\n  function expand_sub_term(sub_term, already_expanding) {\n    var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n    return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n  }\n\n  function normalise(pattern) {\n    return pattern.toString().replace(/^\\/|\\/$/g, '');\n  }\n\n  function is_defined(term) {\n    return !!definitions[term];\n  }\n\n  function is_expandable(text) {\n    return term_grouping_pattern.test(text);\n  }\n\n  function is_compatible(converters, pattern) {\n    return count_converter_arguments(converters) === count_matching_groups(pattern);\n  }\n\n  function get_converters(text) {\n    return $(text.split(term_splitting_pattern)).inject($(), function (converters, fragment) {\n      return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment) : get_matching_group_converters(fragment));\n    });\n  }\n\n  function get_matching_group_converters(text) {\n    return $().fill(pass_through_converter, count_matching_groups(text));\n  }\n\n  function get_sub_term_converters(text) {\n    return get_sub_terms(text).inject($(), function (converters, sub_term) {\n      return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters) : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n    });\n  }\n\n  function count_matching_groups(pattern) {\n    return new RegExp(pattern + '|').exec('').length - 1;\n  }\n\n  function count_converter_arguments(converters) {\n    return $(converters).inject(0, function (sum, converter) {\n      return sum + converter.length - 1;\n    });\n  }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n  var event_handlers = $();\n\n  this.send = function (event_name, event_data, next) {\n    if (arguments.length === 1) return this.send(event_name, {});\n    if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n    notify_handlers(event_name, event_data);\n    next && next();\n    return this;\n  };\n\n  this.on = function (event_pattern, callback) {\n    event_handlers.push({ pattern: event_pattern, callback: callback });\n    return this;\n  };\n\n  var notify_handlers = function (event_name, event_data) {\n    find_handlers(event_name).each(function (callback) {\n      callback({ name: event_name, data: event_data });\n    });\n  };\n\n  var find_handlers = function (event_name) {\n    return event_handlers\n      .find_all(function (handler) {\n        return new RegExp(handler.pattern).test(event_name);\n      })\n      .collect(function (handler) {\n        return handler.callback;\n      });\n  };\n}\n\nfunction instance() {\n  return event_bus;\n}\n\nmodule.exports = {\n  instance: instance,\n  ON_SCENARIO: '__ON_SCENARIO__',\n  ON_STEP: '__ON_STEP__',\n  ON_EXECUTE: '__ON_EXECUTE__',\n  ON_DEFINE: '__ON_DEFINE__',\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n'use strict';\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function (directories) {\n  this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n'use strict';\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function (directories, patterns) {\n  // eslint-disable-next-line no-redeclare\n  var patterns = patterns || /.*/;\n\n  this.each = function (fn) {\n    this.list().forEach(fn);\n  };\n\n  this.list = function () {\n    return $(directories).inject($(), function (files, directory) {\n      return files.concat(list_files(directory).find_all(by_pattern));\n    });\n  };\n\n  var list_files = function (directory) {\n    return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n  };\n\n  var list_immediate_files = function (directory) {\n    return ls(directory).find_all(by_file);\n  };\n\n  var list_sub_directory_files = function (directory) {\n    return ls(directory)\n      .find_all(by_directory)\n      .inject($(), function (files, directory) {\n        return files.concat(list_files(directory));\n      });\n  };\n\n  var ls = function (directory) {\n    if (!fs.existsSync(directory)) return $();\n    return $(fs.readdirSync(directory)).collect(function (file) {\n      return path.join(directory, file);\n    });\n  };\n\n  var by_file = function (file) {\n    return !by_directory(file);\n  };\n\n  var by_directory = function (file) {\n    return fs.statSync(file).isDirectory();\n  };\n\n  var by_pattern = function (filename) {\n    return $(patterns).find(function (pattern) {\n      return new RegExp(pattern).test(filename);\n    });\n  };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n'use strict';\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function (libraries) {\n  // eslint-disable-next-line no-redeclare\n  var libraries = $(libraries);\n  var event_bus = EventBus.instance();\n  var last_macro;\n  var _this = this;\n\n  this.requires = function (libs) {\n    libraries.push_all(libs);\n    return this;\n  };\n\n  this.validate = function (scenario) {\n    var results = $(scenario).collect(function (step) {\n      var report = _this.rank_macros(step).validate();\n      last_macro = report.winner;\n      return report;\n    });\n    if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n  };\n\n  function by_invalid_step(result) {\n    return !result.valid;\n  }\n\n  function validation_report(result) {\n    return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n  }\n\n  this.interpret = function (scenario, scenario_context, next) {\n    scenario_context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n    var iterator = make_step_iterator(scenario_context, next);\n    $(scenario).each_async(iterator, next);\n  };\n\n  var make_step_iterator = function (scenario_context, next) {\n    var iterator = function (step, index, callback) {\n      _this.interpret_step(step, scenario_context, callback);\n    };\n    return next ? iterator : fn.asynchronize(null, iterator);\n  };\n\n  this.interpret_step = function (step, scenario_context, next) {\n    var context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n    var macro = this.rank_macros(step).clear_winner();\n    last_macro = macro;\n    macro.interpret(step, context || {}, next);\n  };\n\n  this.rank_macros = function (step) {\n    return new Competition(step, compatible_macros(step), last_macro);\n  };\n\n  var compatible_macros = function (step) {\n    return libraries.inject([], function (macros, library) {\n      return macros.concat(library.find_compatible_macros(step));\n    });\n  };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n'use strict';\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function (dictionary) {\n  // eslint-disable-next-line no-redeclare\n  var dictionary = dictionary || new Dictionary();\n  var macros = $();\n  var _this = this;\n\n  this.define = function (signatures, fn, macro_context, options) {\n    $(signatures).each(function (signature) {\n      define_macro(signature, fn, macro_context, options);\n    });\n    return this;\n  };\n\n  var define_macro = function (signature, fn, macro_context, options) {\n    if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n    macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n  };\n\n  this.get_macro = function (signature) {\n    return macros.find(function (other_macro) {\n      return other_macro.is_identified_by(signature);\n    });\n  };\n\n  this.find_compatible_macros = function (step) {\n    return macros.find_all(function (macro) {\n      return macro.can_interpret(step);\n    });\n  };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n'use strict';\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function (signature, parsed_signature, macro, macro_context, library, options) {\n  /* eslint-disable no-redeclare */\n  var signature = normalise(signature);\n  var signature_pattern = new RegularExpression(parsed_signature.pattern);\n  var macro = macro || fn.async_noop;\n  var event_bus = EventBus.instance();\n  var options = options || {};\n  /* eslint-enable no-redeclare */\n\n  this.library = library;\n\n  this.is_identified_by = function (other_signature) {\n    return signature === normalise(other_signature);\n  };\n\n  this.can_interpret = function (step) {\n    return signature_pattern.test(step);\n  };\n\n  this.interpret = function (step, scenario_context, next) {\n    var context = new Context({ step: step }).merge(macro_context).merge(scenario_context);\n    convert(signature_pattern.groups(step), function (err, args) {\n      if (err) return next(err);\n      event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n      var result;\n      try {\n        result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n      } catch (err) {\n        if (next) return next(err);\n        throw err;\n      }\n      if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n      if (is_sync(args)) return next && next();\n    });\n  };\n\n  this.is_sibling = function (other_macro) {\n    return other_macro && other_macro.defined_in(library);\n  };\n\n  this.defined_in = function (other_library) {\n    return library === other_library;\n  };\n\n  this.levenshtein_signature = function () {\n    return signature_pattern.without_expressions();\n  };\n\n  this.toString = function () {\n    return signature;\n  };\n\n  function is_promise(result) {\n    if (options.mode) return options.mode === 'promise';\n    return result && result.then;\n  }\n\n  function is_sync(args) {\n    if (options.mode) return options.mode === 'sync';\n    return macro !== fn.async_noop && macro.length !== args.length + 1;\n  }\n\n  function normalise(signature) {\n    return new RegExp(signature).toString();\n  }\n\n  function convert(args, next) {\n    var index = 0;\n    return $(parsed_signature.converters)\n      .collect(function (converter) {\n        return function (callback) {\n          converter.apply(null, args.slice(index, (index += converter.length - 1)).concat(callback));\n        };\n      })\n      .collect_async(function (converter, index, callback) {\n        converter(callback);\n      }, next);\n  }\n\n  event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){(function (){\n'use strict';\n\nmodule.exports = Platform;\n\nfunction Platform() {\n  function get_container() {\n    /* eslint-disable no-undef */\n    if (is_browser()) return window;\n    if (is_phantom()) return phantom;\n    if (is_node()) return global;\n    /* eslint-enable no-undef */\n  }\n\n  function is_node() {\n    return typeof process !== 'undefined' && typeof global !== 'undefined' && typeof __dirname !== 'undefined';\n  }\n\n  function is_browser() {\n    return typeof window !== 'undefined';\n  }\n\n  function is_phantom() {\n    return typeof phantom !== 'undefined';\n  }\n\n  function is_karma() {\n    return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n  }\n\n  return {\n    get_container: get_container,\n    is_node: is_node,\n    is_browser: is_browser,\n    is_phantom: is_phantom,\n    is_karma: is_karma,\n  };\n}\n\n}).call(this)}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function (pattern_or_regexp) {\n  var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n  var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n  var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n  var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n  var non_word_tokens_pattern = /[^\\w\\s]/g;\n  var regexp = new RegExp(pattern_or_regexp);\n\n  this.test = function (text) {\n    var result = regexp.test(text);\n    this.reset();\n    return result;\n  };\n\n  this.groups = function (text) {\n    var results = $();\n    var match = regexp.exec(text);\n    while (match) {\n      var groups = match.slice(1, match.length);\n      results.push(groups);\n      match = regexp.global && regexp.exec(text);\n    }\n    this.reset();\n    return results.flatten();\n  };\n\n  this.reset = function () {\n    regexp.lastIndex = 0;\n    return this;\n  };\n\n  this.without_expressions = function () {\n    return regexp.source.replace(groups_pattern, '$1').replace(sets_pattern, '$1').replace(repetitions_pattern, '$1').replace(regex_aliases_pattern, '$1').replace(non_word_tokens_pattern, '');\n  };\n\n  this.equals = function (other) {\n    return this.toString() === other.toString();\n  };\n\n  this.toString = function () {\n    return '/' + regexp.source + '/';\n  };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  trim: function trim(text) {\n    return text.replace(/^\\s+|\\s+$/g, '');\n  },\n  rtrim: function rtrim(text) {\n    return text.replace(/\\s+$/g, '');\n  },\n  isBlank: function isBlank(text) {\n    return /^\\s*$/g.test(text);\n  },\n  isNotBlank: function isNotBlank(text) {\n    return !this.isBlank(text);\n  },\n  indentation: function indentation(text) {\n    var match = /^(\\s*)/.exec(text);\n    return (match && match[0].length) || 0;\n  },\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n'use strict';\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function (libraries, interpreter_context) {\n  if (!(this instanceof Yadda)) {\n    return new Yadda(libraries, interpreter_context);\n  }\n\n  this.interpreter = new Interpreter(libraries);\n\n  this.requires = function (libraries) {\n    this.interpreter.requires(libraries);\n    return this;\n  };\n\n  this.yadda = function (scenario, scenario_context, next) {\n    if (arguments.length === 0) return this;\n    if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n    this.interpreter.validate(scenario);\n    this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n  };\n\n  // Not everyone shares my sense of humour re the recursive api :(\n  // See https://github.com/acuminous/yadda/issues/111\n  this.run = this.yadda;\n\n  this.toString = function () {\n    return 'Yadda 2.2.0 Copyright 2010 Stephen Cresswell';\n  };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function date_converter(value, next) {\n  var converted = Date.parse(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n  return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function float_converter(value, next) {\n  var converted = parseFloat(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n  return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  date: require('./date-converter'),\n  integer: require('./integer-converter'),\n  float: require('./float-converter'),\n  list: require('./list-converter'),\n  table: require('./table-converter'),\n  pass_through: require('./pass-through-converter'),\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function integer_converter(value, next) {\n  var converted = parseInt(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n  return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function list_converter(value, next) {\n  return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function pass_through_converter(value, next) {\n  return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\nmodule.exports = function table_converter(value, next) {\n  var rows = value.split(/\\n/);\n  var headings = parse_headings(rows.shift());\n  var handler = is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n  var table = $();\n\n  try {\n    $(rows).each(handler);\n    next(null, collapse(table));\n  } catch (err) {\n    next(err);\n  }\n\n  function handle_single_line_row(row) {\n    if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n    start_new_row();\n    parse_fields(row);\n  }\n\n  function handle_multiline_row(row) {\n    if (is_horizinal_separator(row)) return start_new_row();\n    parse_fields(row);\n  }\n\n  function parse_headings(row) {\n    return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX))\n      .collect(function (value) {\n        return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n      })\n      .naked();\n  }\n\n  function is_horizinal_separator(row) {\n    return DASH_REGEX.test(row);\n  }\n\n  function start_new_row() {\n    table.push({});\n  }\n\n  function parse_fields(row) {\n    var fields = table.last();\n    $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function (field, index) {\n      var column = headings[index].text;\n      var indentation = headings[index].indentation;\n      var text = StringUtils.rtrim(field.substr(indentation));\n      if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n      fields[column] = (fields[column] || []).concat(text);\n    });\n  }\n\n  function collapse(table) {\n    return table\n      .collect(function (row) {\n        var new_row = {};\n        for (var heading in row) {\n          new_row[heading] = row[heading].join('\\n');\n        }\n        return new_row;\n      })\n      .naked();\n  }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  var slice = Array.prototype.slice;\n\n  function curry(ctx, fn) {\n    var args = slice.call(arguments, 2);\n    return function () {\n      return fn.apply(ctx, args.concat(slice.call(arguments)));\n    };\n  }\n\n  function invoke(fn, ctx, args) {\n    return fn.apply(ctx, args);\n  }\n\n  function is_function(object) {\n    var getType = {};\n    return object && getType.toString.call(object) === '[object Function]';\n  }\n\n  function noop() {}\n\n  function noargs(fn) {\n    return function () {\n      return fn();\n    };\n  }\n\n  function asynchronize(ctx, fn) {\n    return function () {\n      var next = slice.call(arguments, arguments.length - 1)[0];\n      var args = slice.call(arguments, 0, arguments.length - 2);\n      fn.apply(ctx, args);\n      if (next) next();\n    };\n  }\n\n  return {\n    noop: noop,\n    noargs: noargs,\n    async_noop: asynchronize(null, noop),\n    asynchronize: asynchronize,\n    is_function: is_function,\n    curry: curry,\n    invoke: invoke,\n  };\n})();\n\n},{}],23:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature|功能',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\n    examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\n    pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\n    only: '(?:[Oo]nly|仅仅?)',\n    background: '[Bb]ackground|背景|前提',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Chinese', vocabulary);\n})();\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n    scenario: '(?:[Ss]cenario|[Gg|eval)',\n    examples: '(?:[Vv]oorbeelden?)',\n    pending: '(?:[Tt]odo|[Mm]oet nog)',\n    only: '(?:[Aa]lleen)',\n    background: '(?:[Aa]chtergrond)',\n    given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n    when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n    then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n    examples: '(?:[Ee]xamples|[Ww]here)',\n    pending: '(?:[Pp]ending|[Tt]odo)',\n    only: '(?:[Oo]nly)',\n    background: '[Bb]ackground',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]onctionnalité)',\n    scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n    examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n    pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n    only: '(?:[Ss]eulement])',\n    background: '(?:[Cc]ontexte)',\n    given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n    when: \"(?:[Qq]uand|[Ll]orsqu'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)\",\n    then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n    _steps: ['given', 'when', 'then', 'soit', 'etantdonnees', 'etantdonnee', 'etantdonne', 'quand', 'lorsque', 'alors'],\n    // Also aliasing French verbs for given-when-then for signature-lookup\n    get soit() {\n      return this.given;\n    },\n    get etantdonnees() {\n      return this.given;\n    },\n    get etantdonnee() {\n      return this.given;\n    },\n    get etantdonne() {\n      return this.given;\n    },\n    get quand() {\n      return this.when;\n    },\n    get lorsque() {\n      return this.when;\n    },\n    get alors() {\n      return this.then;\n    },\n  };\n\n  return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n    scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n    examples: '(?:[Bb]eispiele?)',\n    pending: '(?:[Tt]odo|[Oo]ffen)',\n    only: '(?:[Nn]ur|[Ee]inzig)',\n    background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n    given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n    when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n    then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n'use strict';\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function (name, vocabulary) {\n  var _this = this;\n\n  // See http://github.com/acuminous/yadda#203\n  this.is_language = true;\n\n  this.library = function (dictionary) {\n    return _this.localise_library(new Library(dictionary));\n  };\n\n  this.localise_library = function (library) {\n    $(vocabulary._steps).each(function (keyword) {\n      library[keyword] = function (signatures, fn, ctx, options) {\n        return $(signatures).each(function (signature) {\n          signature = prefix_signature(_this.localise(keyword), signature);\n          return library.define(signature, fn, ctx, options);\n        });\n      };\n    });\n    return library;\n  };\n\n  var prefix_signature = function (prefix, signature) {\n    var regex_delimiters = new RegExp('^/|/$', 'g');\n    var start_of_signature = new RegExp(/^(?:\\^)?/);\n    var one_or_more_spaces = '\\\\s+';\n    var leading_spaces = '^(?:\\\\s)*';\n    return signature\n      .toString()\n      .replace(regex_delimiters, '')\n      .replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n  };\n\n  this.localise = function (keyword) {\n    if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n    return vocabulary[keyword];\n  };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ee]genskap',\n    scenario: '[Ss]cenario',\n    examples: '[Ee]ksempler',\n    pending: '[Aa]vventer',\n    only: '[Bb]are',\n    background: '[Bb]akgrunn',\n    given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n    when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n    then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n    _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n    // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n    get gitt() {\n      return this.given;\n    },\n    get når() {\n      return this.when;\n    },\n    get så() {\n      return this.then;\n    },\n  };\n\n  return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Tt]ale|[Yy]arn)',\n    scenario: '(?:[Aa]dventure|[Ss]ortie)',\n    examples: '[Ww]herest',\n    pending: '[Bb]rig',\n    only: '[Bb]lack [Ss]pot',\n    background: '[Aa]ftground',\n    given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n    // Also aliasing Pirate verbs for given-when-then for signature-lookup\n    get giveth() {\n      return this.given;\n    },\n    get whence() {\n      return this.when;\n    },\n    get thence() {\n      return this.then;\n    },\n  };\n\n  return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n    scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n    examples: '[Pp]rzykłady',\n    pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n    only: '[Tt]ylko',\n    background: '[Zz]ałożenia',\n    given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n    when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n    then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n    _steps: ['given', 'when', 'then', 'zakladajac', 'majac', 'jezeli', 'jesli', 'gdy', 'kiedy', 'wtedy'],\n    // Also aliasing Polish verbs for given-when-then for signature-lookup\n    get zakladajac() {\n      return this.given;\n    },\n    get majac() {\n      return this.given;\n    },\n    get jezeli() {\n      return this.when;\n    },\n    get jesli() {\n      return this.when;\n    },\n    get gdy() {\n      return this.when;\n    },\n    get kiedy() {\n      return this.when;\n    },\n    get wtedy() {\n      return this.then;\n    },\n  };\n\n  return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n    scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n    examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n    pending: '[Pp]endente',\n    only: '[S][óo]',\n    background: '[Ff]undo',\n    given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n    when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n    then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n    _steps: ['given', 'when', 'then', 'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas', 'quando', 'se', 'entao'],\n\n    get seja() {\n      return this.given;\n    },\n    get sejam() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get quando() {\n      return this.when;\n    },\n    get se() {\n      return this.when;\n    },\n    get entao() {\n      return this.then;\n    },\n  };\n\n  return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n    scenario: 'Сценарий',\n    examples: 'Примеры?',\n    pending: '(?:[Ww]ip|[Tt]odo)',\n    only: 'Только',\n    background: '(?:[Пп]редыстория|[Кк]онтекст)',\n    given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n    scenario: '(?:[Ee]scenario|[Cc]aso)',\n    examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n    pending: '[Pp]endiente',\n    only: '[S]ólo',\n    background: '[Ff]ondo',\n    given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n    when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n    then: '(?:[Ee]ntonces)',\n\n    _steps: ['given', 'when', 'then', 'sea', 'sean', 'dado', 'dada', 'dados', 'dadas', 'cuando', 'si', 'entonces'],\n\n    get sea() {\n      return this.given;\n    },\n    get sean() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get cuando() {\n      return this.when;\n    },\n    get si() {\n      return this.when;\n    },\n    get entonces() {\n      return this.then;\n    },\n  };\n\n  return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n    scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n    examples: '[Пп]риклади',\n    pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n    only: '[Тт]ільки',\n    background: '[Кк]онтекст',\n    given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n    when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n    then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  Chinese: require('./Chinese'),\n  English: require('./English'),\n  French: require('./French'),\n  German: require('./German'),\n  Dutch: require('./Dutch'),\n  Norwegian: require('./Norwegian'),\n  Pirate: require('./Pirate'),\n  Ukrainian: require('./Ukrainian'),\n  Polish: require('./Polish'),\n  Spanish: require('./Spanish'),\n  Russian: require('./Russian'),\n  Portuguese: require('./Portuguese'),\n  default: require('./English'),\n  Language: require('./Language'),\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n'use strict';\n\nvar FeatureFileParser = function (options) {\n  var fs = require('../shims').fs;\n  var FeatureParser = require('./FeatureParser');\n  var parser = new FeatureParser(options);\n\n  this.parse = function (file, next) {\n    var text = fs.readFileSync(file, 'utf8');\n    var feature = parser.parse(text);\n    return (next && next(feature)) || feature;\n  };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function (options) {\n  /* eslint-disable no-redeclare */\n  var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']' };\n  var options = options && options.is_language ? { language: options } : options || defaults;\n  var language = options.language || defaults.language;\n  var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n  var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n  /* eslint-enable no-redeclare */\n\n  var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n  var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n  var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n  var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n  var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n  var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n  var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n  var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n  var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n  var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n  var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n  var specification;\n  var comment;\n\n  this.parse = function (text, next) {\n    reset();\n    split(text).each(parse_line);\n    return (next && next(specification.export())) || specification.export();\n  };\n\n  function reset() {\n    specification = new Specification();\n    comment = false;\n  }\n\n  function split(text) {\n    return $(text.split(/\\r\\n|\\n/));\n  }\n\n  function parse_line(line, index) {\n    var match;\n    var line_number = index + 1;\n    try {\n      // eslint-disable-next-line no-return-assign\n      if ((match = MULTI_LINE_COMMENT_REGEX.test(line))) return (comment = !comment);\n      if (comment) return;\n      if ((match = SINGLE_LINE_COMMENT_REGEX.test(line))) return;\n      if ((match = SIMPLE_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n      if ((match = NVP_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n      if ((match = FEATURE_REGEX.exec(line))) return specification.handle('Feature', match[1], line_number);\n      if ((match = SCENARIO_REGEX.exec(line))) return specification.handle('Scenario', match[1], line_number);\n      if ((match = BACKGROUND_REGEX.exec(line))) return specification.handle('Background', match[1], line_number);\n      if ((match = EXAMPLES_REGEX.exec(line))) return specification.handle('Examples', line_number);\n      if ((match = BLANK_REGEX.exec(line))) return specification.handle('Blank', match[0], line_number);\n      if ((match = DASH_REGEX.exec(line))) return specification.handle('Dash', match[1], line_number);\n      if ((match = TEXT_REGEX.exec(line))) return specification.handle('Text', match[1], line_number);\n    } catch (e) {\n      e.message = 'Error parsing line ' + line_number + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n      throw e;\n    }\n  }\n\n  var Handlers = function (handlers) {\n    // eslint-disable-next-line no-redeclare\n    var handlers = handlers || {};\n\n    this.register = function (event, handler) {\n      handlers[event] = handler;\n    };\n\n    this.unregister = function () {\n      $(Array.prototype.slice.call(arguments)).each(function (event) {\n        delete handlers[event];\n      });\n    };\n\n    this.find = function (event) {\n      if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n      return { handle: handlers[event.toLowerCase()] };\n    };\n  };\n\n  var Specification = function () {\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      text: fn.noop,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      feature: start_feature,\n      scenario: start_scenario,\n      background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n      // eslint-disable-next-line no-return-assign\n      return (feature = new Feature(title, annotations, new Annotations()));\n    }\n\n    function start_scenario(event, title, line_number) {\n      feature = new Feature(title, new Annotations(), annotations);\n      return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function (event, data, line_number) {\n      current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      if (!feature) throw new Error('A feature must contain one or more scenarios');\n      return feature.export();\n    };\n  };\n\n  var Annotations = function () {\n    var annotations = {};\n\n    this.stash = function (key, value) {\n      if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n      annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function () {\n      return annotations;\n    };\n  };\n\n  var Feature = function (title, annotations, stashed_annotations) {\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n      text: capture_description,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n      background: start_background,\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n      background = new Background(title, _this);\n      stashed_annotations = new Annotations();\n      return background;\n    }\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background', 'text');\n      stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n      description.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, title) {\n      var scenario = new Scenario(title, background, stashed_annotations, _this);\n      scenarios.push(scenario);\n      stashed_annotations = new Annotations();\n      return scenario;\n    }\n\n    function validate() {\n      if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        scenarios: $(scenarios)\n          .collect(function (scenario) {\n            return scenario.export();\n          })\n          .flatten()\n          .naked(),\n      };\n    };\n  };\n\n  var Background = function (title, feature) {\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n    });\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', stash_annotation);\n      handlers.register('scenario', start_scenario);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      validate();\n      return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        steps: steps,\n      };\n    };\n  };\n\n  var NullBackground = function () {\n    var handlers = new Handlers();\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      return {\n        steps: [],\n      };\n    };\n  };\n\n  var Scenario = function (title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: start_scenario,\n      scenario: start_scenario,\n      examples: start_examples,\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n      handlers.register('examples', start_examples);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n      validate();\n      examples = new Examples(_this);\n      return examples;\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      var result = {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        steps: background.export().steps.concat(steps),\n      };\n      return examples ? examples.expand(result) : result;\n    };\n  };\n\n  var Examples = function (scenario) {\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      blank: fn.noop,\n      dash: start_example_table,\n      text: capture_headings,\n    });\n\n    function start_example_table(evnet, data, line_number) {\n      handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n      handlers.register('annotation', stash_annotation);\n      handlers.register('text', capture_singleline_fields);\n      handlers.register('dash', enable_multiline_examples);\n      var pos = 1;\n      headings = split(data)\n        .collect(function (column) {\n          var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n          pos += column.length + 1;\n          return attributes;\n        })\n        .naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      handlers.unregister('blank', 'dash');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n      handlers.register('dash', end_example_table);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n      annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', continue_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n      parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n      handlers.unregister('text', 'dash');\n      handlers.register('blank', fn.noop);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n      var fields = examples.last().fields;\n      $(headings).each(function (heading) {\n        fields[heading.text + '.index'] = [examples.length];\n        fields[heading.text + '.start.line'] = [line_number];\n        fields[heading.text + '.start.column'] = [heading.left + heading.indentation];\n      });\n    }\n\n    function parse_fields(row, fields) {\n      split(row, headings.length).each(function (field, index) {\n        var column = headings[index].text;\n        var indentation = headings[index].indentation;\n        var text = StringUtils.rtrim(field.substr(indentation));\n        if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n        fields[column] = (fields[column] || []).concat(text);\n      });\n      return fields;\n    }\n\n    function split(row, number_of_fields) {\n      var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n      var fields = $(row.split(separator));\n      if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n        throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n      }\n      return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n      if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function (scenario) {\n      validate();\n      return examples\n        .collect(function (example) {\n          return {\n            title: substitute(example.fields, scenario.title),\n            annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n            description: substitute_all(example, scenario.description),\n            steps: substitute_all(example.fields, scenario.steps),\n          };\n        })\n        .naked();\n    };\n\n    function shallow_merge() {\n      var result = {};\n      $(Array.prototype.slice.call(arguments)).each(function (annotations) {\n        for (var key in annotations) {\n          result[key] = annotations[key];\n        }\n      });\n      return result;\n    }\n\n    function substitute_all(example, lines) {\n      return $(lines)\n        .collect(function (line) {\n          return substitute(example, line);\n        })\n        .naked();\n    }\n\n    function substitute(example, line) {\n      for (var heading in example) {\n        line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n      }\n      return line;\n    }\n  };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\n\nvar StepParser = function () {\n  var NON_BLANK_REGEX = /[^\\s]/;\n\n  this.parse = function (text, next) {\n    var steps = split(text).find_all(non_blanks);\n    return (next && next(steps)) || steps;\n  };\n\n  var split = function (text) {\n    return $(text.split(/\\n/));\n  };\n\n  var non_blanks = function (text) {\n    return text && NON_BLANK_REGEX.test(text);\n  };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  StepParser: require('./StepParser'),\n  FeatureParser: require('./FeatureParser'),\n  FeatureFileParser: require('./FeatureFileParser'),\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){(function (){\n'use strict';\n\nif (!module.client) {\n  var fs = require('../shims').fs;\n  global.process = global.process || {\n    cwd: function () {\n      return fs.workingDirectory;\n    },\n  };\n}\n\nmodule.exports = function (yadda, casper) {\n  var EventBus = require('yadda').EventBus;\n\n  yadda.interpreter.interpret_step = function (step, ctx, next) {\n    var _this = this;\n    casper.then(function () {\n      casper.test.info(step);\n      EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n      _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    });\n  };\n\n  casper.yadda = function (script, ctx) {\n    if (script === undefined) return this;\n    yadda.run(script, ctx);\n  };\n};\n\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  casper: require('./CasperPlugin'),\n  mocha: {\n    ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n    StepLevelPlugin: require('./mocha/StepLevelPlugin'),\n  },\n  get jasmine() {\n    return this.mocha;\n  },\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n'use strict';\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function (options) {\n  /* jslint shadow: true */\n  var platform = new Platform();\n  var language = options.language || Localisation.default;\n  var parser = options.parser || new FeatureFileParser(options);\n  var container = options.container || platform.get_container();\n\n  function featureFiles(files, iterator) {\n    $(files).each(function (file) {\n      features(parser.parse(file), iterator);\n    });\n  }\n\n  function features(features, iterator) {\n    $(features).each(function (feature) {\n      describe(feature.title, feature, iterator);\n    });\n  }\n\n  function describe(title, subject, iterator) {\n    var _describe = getDescribe(subject.annotations);\n    _describe(title, function () {\n      iterator(subject);\n    });\n  }\n\n  function it_async(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function (done) {\n      iterator(this, subject, done);\n    });\n  }\n\n  function it_sync(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function () {\n      iterator(this, subject);\n    });\n  }\n\n  function getIt(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xit;\n    if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n    return container.it;\n  }\n\n  function getDescribe(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xdescribe;\n    if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n    return container.describe;\n  }\n\n  function has_annotation(annotations, name) {\n    var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n    for (var key in annotations) {\n      if (regexp.test(key)) return true;\n    }\n  }\n\n  return {\n    featureFiles: featureFiles,\n    features: features,\n    describe: describe,\n    it_async: it_async,\n    it_sync: it_sync,\n  };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n      itFn(scenario.title, scenario, function (context, scenario, done) {\n        iterator(scenario, done);\n      });\n    });\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      base_plugin.describe(scenario.title, scenario, iterator);\n    });\n  }\n\n  function steps(steps, iterator) {\n    var abort = false;\n\n    $(steps).each(function (step) {\n      var stepFn = iterator.length === 1 ? step_sync : step_async;\n      stepFn(step, iterator);\n    });\n\n    function step_async(step, iterator) {\n      base_plugin.it_async(step, step, function (context, step, done) {\n        if (abort) {\n          return context.skip ? context.skip() : done();\n        }\n        abort = true;\n        iterator.bind(context)(step, function (err) {\n          if (err) return (done.fail || done)(err);\n          abort = false;\n          done();\n        });\n      });\n    }\n\n    function step_sync(step, iterator) {\n      base_plugin.it_sync(step, step, function (context, step) {\n        if (abort) return context.skip && context.skip();\n        abort = true;\n        iterator.bind(context)(step);\n        abort = false;\n      });\n    }\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n  container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n'use strict';\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function (s1, s2) {\n  this.value;\n  this.type = 'LevenshteinDistanceScore';\n  var distance_table;\n  var _this = this;\n\n  var initialise = function () {\n    var x = s1.length;\n    var y = s2.length;\n\n    distance_table = new Array(x + 1);\n\n    /* eslint-disable no-redeclare */\n    for (var i = 0; i <= x; i++) {\n      distance_table[i] = new Array(y + 1);\n    }\n\n    for (var i = 0; i <= x; i++) {\n      for (var j = 0; j <= y; j++) {\n        distance_table[i][j] = 0;\n      }\n    }\n\n    for (var i = 0; i <= x; i++) {\n      distance_table[i][0] = i;\n    }\n\n    for (var j = 0; j <= y; j++) {\n      distance_table[0][j] = j;\n    }\n    /* eslint-enable no-redeclare */\n  };\n\n  var score = function () {\n    // eslint-disable-next-line no-return-assign\n    if (s1 === s2) return (_this.value = 0);\n\n    for (var j = 0; j < s2.length; j++) {\n      for (var i = 0; i < s1.length; i++) {\n        if (s1[i] === s2[j]) {\n          distance_table[i + 1][j + 1] = distance_table[i][j];\n        } else {\n          var deletion = distance_table[i][j + 1] + 1;\n          var insertion = distance_table[i + 1][j] + 1;\n          var substitution = distance_table[i][j] + 1;\n          distance_table[i + 1][j + 1] = Math.min(substitution, deletion, insertion);\n        }\n      }\n    }\n    _this.value = distance_table[s1.length][s2.length];\n  };\n\n  this.compare = function (other) {\n    return other.value - this.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n\n  initialise();\n  score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\n\nvar MultiScore = function (scores) {\n  this.scores = $(scores);\n  this.type = 'MultiScore';\n\n  this.compare = function (other) {\n    for (var i = 0; i < this.scores.length; i++) {\n      var difference = this.scores[i].compare(other.scores[i]);\n      if (difference) return difference;\n    }\n    return 0;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    if (this.type !== other.type) return false;\n    return this.compare(other) === 0;\n  };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n'use strict';\n\nvar SameLibraryScore = function (m1, m2) {\n  this.value = m1.is_sibling(m2) ? 1 : 0;\n  this.type = 'SameLibraryScore';\n\n  this.compare = function (other) {\n    return this.value - other.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){(function (){\n'use strict';\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n  var platform = new Platform();\n\n  var shims = {\n    node: function () {\n      return {\n        fs: require('fs'),\n        path: require('path'),\n        process: process,\n      };\n    },\n    phantom: function () {\n      return {\n        fs: require('./phantom-fs'),\n        path: require('./phantom-path'),\n        process: require('./phantom-process'),\n      };\n    },\n    karma: function () {\n      return {\n        fs: require('./karma-fs'),\n        path: require('./karma-path'),\n        process: require('./karma-process'),\n      };\n    },\n  };\n\n  function get_shim() {\n    if (platform.is_phantom()) return shims.phantom();\n    if (platform.is_browser() && platform.is_karma()) return shims.karma();\n    if (platform.is_node()) return shims.node();\n    return {};\n  }\n\n  return get_shim();\n})();\n\n}).call(this)}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var path = require('./karma-path');\n\n  function absolutePath(relativePath) {\n    return path.resolve(path.normalize(relativePath.split('\\\\').join('/')));\n  }\n\n  var KarmaFileSystem = function () {\n    this.registry = new KarmaPathRegistry();\n    this.converter = new KarmaUriPathConverter('/base/', '/');\n    this.reader = new KarmaFileReader(this.converter);\n\n    var servedUris = Object.keys(window.__karma__.files);\n    var servedFiles = this.converter.parseUris(servedUris);\n    servedFiles.forEach(this.registry.addFile, this.registry);\n  };\n  KarmaFileSystem.prototype = {\n    constructor: KarmaFileSystem,\n    workingDirectory: '/',\n    existsSync: function (path) {\n      return this.registry.exists(path);\n    },\n    readdirSync: function (path) {\n      return this.registry.getContent(path);\n    },\n    statSync: function (path) {\n      return {\n        isDirectory: function () {\n          return this.registry.isDirectory(path);\n        }.bind(this),\n      };\n    },\n    readFileSync: function (file, encoding) {\n      if (encoding !== 'utf8') throw new Error('This fs.readFileSync() shim does not support other than utf8 encoding.');\n      if (!this.registry.isFile(file)) throw new Error('File does not exist: ' + file);\n      return this.reader.readFile(file);\n    },\n  };\n\n  var KarmaPathRegistry = function KarmaPathRegistry() {\n    this.paths = {};\n  };\n\n  KarmaPathRegistry.prototype = {\n    constructor: KarmaPathRegistry,\n    addFile: function (file) {\n      file = absolutePath(file);\n      this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n      var parentDirectory = path.dirname(file);\n      this.addDirectory(parentDirectory);\n    },\n    addDirectory: function (directory) {\n      directory = absolutePath(directory);\n      this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n      var parentDirectory = path.dirname(directory);\n      if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n    },\n    isFile: function (file) {\n      file = absolutePath(file);\n      return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n    },\n    isDirectory: function (directory) {\n      directory = absolutePath(directory);\n      return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n    },\n    exists: function (node) {\n      node = absolutePath(node);\n      return this.paths.hasOwnProperty(node);\n    },\n    getContent: function (directory) {\n      if (!this.isDirectory(directory)) throw new Error('Not a directory: ' + directory);\n      directory = absolutePath(directory);\n      return Object.keys(this.paths)\n        .filter(function (node) {\n          if (node === directory) return false;\n          var parentDirectory = path.dirname(node);\n          return parentDirectory === directory;\n        }, this)\n        .map(function (node) {\n          return path.basename(node);\n        });\n    },\n  };\n\n  KarmaPathRegistry.TYPE_FILE = 0;\n  KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n  var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n    this.workingDirectory = workingDirectory;\n    this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n    this.baseUri = baseUri;\n    this.baseUriPattern = this.patternFromBase(baseUri);\n  };\n\n  KarmaUriPathConverter.prototype = {\n    constructor: KarmaUriPathConverter,\n    patternFromBase: function (string, flags) {\n      var pattern = '^' + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n      return new RegExp(pattern, flags);\n    },\n    parseUris: function (uris) {\n      return uris\n        .filter(function (uri) {\n          return this.baseUriPattern.test(uri);\n        }, this)\n        .map(function (uri) {\n          return uri.replace(this.baseUriPattern, this.workingDirectory);\n        }, this);\n    },\n    buildUri: function (file) {\n      file = absolutePath(file);\n      if (!this.workingDirectoryPattern.test(file)) throw new Error('Path is not in working directory: ' + file);\n      return file.replace(this.workingDirectoryPattern, this.baseUri);\n    },\n  };\n\n  var KarmaFileReader = function KarmaFileReader(converter) {\n    this.converter = converter;\n  };\n\n  KarmaFileReader.prototype = {\n    constructor: KarmaFileReader,\n    readFile: function (file) {\n      var uri = this.converter.buildUri(file);\n      // eslint-disable-next-line no-undef\n      var xhr = new XMLHttpRequest();\n      xhr.open('get', uri, false);\n      xhr.send();\n      return xhr.responseText;\n    },\n  };\n\n  return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n  }\n\n  if (typeof path.normalize !== 'function' || typeof path.dirname !== 'function') throw new Error('The path module emulation does not contain implementations of required functions.');\n\n  return path;\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var fs = require('./karma-fs');\n  var process = {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n\n  fs.existsSync = fs.existsSync || fs.exists;\n\n  fs.readdirSync =\n    fs.readdirSync ||\n    function (path) {\n      return fs.list(path).filter(function (name) {\n        return name !== '.' && name !== '..';\n      });\n    };\n\n  fs.statSync =\n    fs.statSync ||\n    function (path) {\n      return {\n        isDirectory: function () {\n          return fs.isDirectory(path);\n        },\n      };\n    };\n\n  return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    // meh\n  }\n\n  path.join =\n    path.join ||\n    function () {\n      return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n  path.relative =\n    path.relative ||\n    function (from, to) {\n      return from + fs.separator + to;\n    };\n\n  return path;\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var process = typeof process !== 'undefined' ? process : {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){(function (){\n// 'path' module extracted from Node.js v8.11.1 (only the posix part)\n// transplited with Babel\n\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nfunction assertPath(path) {\n  if (typeof path !== 'string') {\n    throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));\n  }\n}\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeStringPosix(path, allowAboveRoot) {\n  var res = '';\n  var lastSegmentLength = 0;\n  var lastSlash = -1;\n  var dots = 0;\n  var code;\n  for (var i = 0; i <= path.length; ++i) {\n    if (i < path.length)\n      code = path.charCodeAt(i);\n    else if (code === 47 /*/*/)\n      break;\n    else\n      code = 47 /*/*/;\n    if (code === 47 /*/*/) {\n      if (lastSlash === i - 1 || dots === 1) {\n        // NOOP\n      } else if (lastSlash !== i - 1 && dots === 2) {\n        if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {\n          if (res.length > 2) {\n            var lastSlashIndex = res.lastIndexOf('/');\n            if (lastSlashIndex !== res.length - 1) {\n              if (lastSlashIndex === -1) {\n                res = '';\n                lastSegmentLength = 0;\n              } else {\n                res = res.slice(0, lastSlashIndex);\n                lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n              }\n              lastSlash = i;\n              dots = 0;\n              continue;\n            }\n          } else if (res.length === 2 || res.length === 1) {\n            res = '';\n            lastSegmentLength = 0;\n            lastSlash = i;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          if (res.length > 0)\n            res += '/..';\n          else\n            res = '..';\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0)\n          res += '/' + path.slice(lastSlash + 1, i);\n        else\n          res = path.slice(lastSlash + 1, i);\n        lastSegmentLength = i - lastSlash - 1;\n      }\n      lastSlash = i;\n      dots = 0;\n    } else if (code === 46 /*.*/ && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\n\nfunction _format(sep, pathObject) {\n  var dir = pathObject.dir || pathObject.root;\n  var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');\n  if (!dir) {\n    return base;\n  }\n  if (dir === pathObject.root) {\n    return dir + base;\n  }\n  return dir + sep + base;\n}\n\nvar posix = {\n  // path.resolve([from ...], to)\n  resolve: function resolve() {\n    var resolvedPath = '';\n    var resolvedAbsolute = false;\n    var cwd;\n\n    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n      var path;\n      if (i >= 0)\n        path = arguments[i];\n      else {\n        if (cwd === undefined)\n          cwd = process.cwd();\n        path = cwd;\n      }\n\n      assertPath(path);\n\n      // Skip empty entries\n      if (path.length === 0) {\n        continue;\n      }\n\n      resolvedPath = path + '/' + resolvedPath;\n      resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    }\n\n    // At this point the path should be resolved to a full absolute path, but\n    // handle relative paths to be safe (might happen when process.cwd() fails)\n\n    // Normalize the path\n    resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);\n\n    if (resolvedAbsolute) {\n      if (resolvedPath.length > 0)\n        return '/' + resolvedPath;\n      else\n        return '/';\n    } else if (resolvedPath.length > 0) {\n      return resolvedPath;\n    } else {\n      return '.';\n    }\n  },\n\n  normalize: function normalize(path) {\n    assertPath(path);\n\n    if (path.length === 0) return '.';\n\n    var isAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;\n\n    // Normalize the path\n    path = normalizeStringPosix(path, !isAbsolute);\n\n    if (path.length === 0 && !isAbsolute) path = '.';\n    if (path.length > 0 && trailingSeparator) path += '/';\n\n    if (isAbsolute) return '/' + path;\n    return path;\n  },\n\n  isAbsolute: function isAbsolute(path) {\n    assertPath(path);\n    return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;\n  },\n\n  join: function join() {\n    if (arguments.length === 0)\n      return '.';\n    var joined;\n    for (var i = 0; i < arguments.length; ++i) {\n      var arg = arguments[i];\n      assertPath(arg);\n      if (arg.length > 0) {\n        if (joined === undefined)\n          joined = arg;\n        else\n          joined += '/' + arg;\n      }\n    }\n    if (joined === undefined)\n      return '.';\n    return posix.normalize(joined);\n  },\n\n  relative: function relative(from, to) {\n    assertPath(from);\n    assertPath(to);\n\n    if (from === to) return '';\n\n    from = posix.resolve(from);\n    to = posix.resolve(to);\n\n    if (from === to) return '';\n\n    // Trim any leading backslashes\n    var fromStart = 1;\n    for (; fromStart < from.length; ++fromStart) {\n      if (from.charCodeAt(fromStart) !== 47 /*/*/)\n        break;\n    }\n    var fromEnd = from.length;\n    var fromLen = fromEnd - fromStart;\n\n    // Trim any leading backslashes\n    var toStart = 1;\n    for (; toStart < to.length; ++toStart) {\n      if (to.charCodeAt(toStart) !== 47 /*/*/)\n        break;\n    }\n    var toEnd = to.length;\n    var toLen = toEnd - toStart;\n\n    // Compare paths to find the longest common path from root\n    var length = fromLen < toLen ? fromLen : toLen;\n    var lastCommonSep = -1;\n    var i = 0;\n    for (; i <= length; ++i) {\n      if (i === length) {\n        if (toLen > length) {\n          if (to.charCodeAt(toStart + i) === 47 /*/*/) {\n            // We get here if `from` is the exact base path for `to`.\n            // For example: from='/foo/bar'; to='/foo/bar/baz'\n            return to.slice(toStart + i + 1);\n          } else if (i === 0) {\n            // We get here if `from` is the root\n            // For example: from='/'; to='/foo'\n            return to.slice(toStart + i);\n          }\n        } else if (fromLen > length) {\n          if (from.charCodeAt(fromStart + i) === 47 /*/*/) {\n            // We get here if `to` is the exact base path for `from`.\n            // For example: from='/foo/bar/baz'; to='/foo/bar'\n            lastCommonSep = i;\n          } else if (i === 0) {\n            // We get here if `to` is the root.\n            // For example: from='/foo'; to='/'\n            lastCommonSep = 0;\n          }\n        }\n        break;\n      }\n      var fromCode = from.charCodeAt(fromStart + i);\n      var toCode = to.charCodeAt(toStart + i);\n      if (fromCode !== toCode)\n        break;\n      else if (fromCode === 47 /*/*/)\n        lastCommonSep = i;\n    }\n\n    var out = '';\n    // Generate the relative path based on the path difference between `to`\n    // and `from`\n    for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n      if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {\n        if (out.length === 0)\n          out += '..';\n        else\n          out += '/..';\n      }\n    }\n\n    // Lastly, append the rest of the destination (`to`) path that comes after\n    // the common path parts\n    if (out.length > 0)\n      return out + to.slice(toStart + lastCommonSep);\n    else {\n      toStart += lastCommonSep;\n      if (to.charCodeAt(toStart) === 47 /*/*/)\n        ++toStart;\n      return to.slice(toStart);\n    }\n  },\n\n  _makeLong: function _makeLong(path) {\n    return path;\n  },\n\n  dirname: function dirname(path) {\n    assertPath(path);\n    if (path.length === 0) return '.';\n    var code = path.charCodeAt(0);\n    var hasRoot = code === 47 /*/*/;\n    var end = -1;\n    var matchedSlash = true;\n    for (var i = path.length - 1; i >= 1; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          if (!matchedSlash) {\n            end = i;\n            break;\n          }\n        } else {\n        // We saw the first non-path separator\n        matchedSlash = false;\n      }\n    }\n\n    if (end === -1) return hasRoot ? '/' : '.';\n    if (hasRoot && end === 1) return '//';\n    return path.slice(0, end);\n  },\n\n  basename: function basename(path, ext) {\n    if (ext !== undefined && typeof ext !== 'string') throw new TypeError('\"ext\" argument must be a string');\n    assertPath(path);\n\n    var start = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i;\n\n    if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n      if (ext.length === path.length && ext === path) return '';\n      var extIdx = ext.length - 1;\n      var firstNonSlashEnd = -1;\n      for (i = path.length - 1; i >= 0; --i) {\n        var code = path.charCodeAt(i);\n        if (code === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else {\n          if (firstNonSlashEnd === -1) {\n            // We saw the first non-path separator, remember this index in case\n            // we need it if the extension ends up not matching\n            matchedSlash = false;\n            firstNonSlashEnd = i + 1;\n          }\n          if (extIdx >= 0) {\n            // Try to match the explicit extension\n            if (code === ext.charCodeAt(extIdx)) {\n              if (--extIdx === -1) {\n                // We matched the extension, so mark this as the end of our path\n                // component\n                end = i;\n              }\n            } else {\n              // Extension does not match, so our result is the entire path\n              // component\n              extIdx = -1;\n              end = firstNonSlashEnd;\n            }\n          }\n        }\n      }\n\n      if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;\n      return path.slice(start, end);\n    } else {\n      for (i = path.length - 1; i >= 0; --i) {\n        if (path.charCodeAt(i) === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else if (end === -1) {\n          // We saw the first non-path separator, mark this as the end of our\n          // path component\n          matchedSlash = false;\n          end = i + 1;\n        }\n      }\n\n      if (end === -1) return '';\n      return path.slice(start, end);\n    }\n  },\n\n  extname: function extname(path) {\n    assertPath(path);\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n    for (var i = path.length - 1; i >= 0; --i) {\n      var code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1)\n            startDot = i;\n          else if (preDotState !== 1)\n            preDotState = 1;\n      } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n        // We saw a non-dot character immediately before the dot\n        preDotState === 0 ||\n        // The (right-most) trimmed path component is exactly '..'\n        preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      return '';\n    }\n    return path.slice(startDot, end);\n  },\n\n  format: function format(pathObject) {\n    if (pathObject === null || typeof pathObject !== 'object') {\n      throw new TypeError('The \"pathObject\" argument must be of type Object. Received type ' + typeof pathObject);\n    }\n    return _format('/', pathObject);\n  },\n\n  parse: function parse(path) {\n    assertPath(path);\n\n    var ret = { root: '', dir: '', base: '', ext: '', name: '' };\n    if (path.length === 0) return ret;\n    var code = path.charCodeAt(0);\n    var isAbsolute = code === 47 /*/*/;\n    var start;\n    if (isAbsolute) {\n      ret.root = '/';\n      start = 1;\n    } else {\n      start = 0;\n    }\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i = path.length - 1;\n\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n\n    // Get non-dir info\n    for (; i >= start; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;\n        } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n    // We saw a non-dot character immediately before the dot\n    preDotState === 0 ||\n    // The (right-most) trimmed path component is exactly '..'\n    preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      if (end !== -1) {\n        if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);\n      }\n    } else {\n      if (startPart === 0 && isAbsolute) {\n        ret.name = path.slice(1, startDot);\n        ret.base = path.slice(1, end);\n      } else {\n        ret.name = path.slice(startPart, startDot);\n        ret.base = path.slice(startPart, end);\n      }\n      ret.ext = path.slice(startDot, end);\n    }\n\n    if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';\n\n    return ret;\n  },\n\n  sep: '/',\n  delimiter: ':',\n  win32: null,\n  posix: null\n};\n\nposix.posix = posix;\n\nmodule.exports = posix;\n\n}).call(this)}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n'use strict';\n\nvar api = {\n  Yadda: require('./Yadda'),\n  EventBus: require('./EventBus'),\n  Interpreter: require('./Interpreter'),\n  Context: require('./Context'),\n  Library: require('./Library'),\n  Dictionary: require('./Dictionary'),\n  FeatureFileSearch: require('./FeatureFileSearch'),\n  FileSearch: require('./FileSearch'),\n  Platform: require('./Platform'),\n  localisation: require('./localisation/index'),\n  converters: require('./converters/index'),\n  parsers: require('./parsers/index'),\n  plugins: require('./plugins/index'),\n  shims: require('./shims/index'),\n  createInstance: function () {\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n  },\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.10.0.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_node()) return global; \n        if (is_phantom()) return phantom;\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '[Ff]ond',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_node()) return shims.node();\n\n        if (platform.is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.1.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '[Ff]ond',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.10.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.10 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');\n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.11.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.11 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');\n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.12.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.12 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.13.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.13 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.14.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.14 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":26,\"./parsers/index\":30,\"./plugins/index\":33,\"./shims/index\":39}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":21}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":21}],20:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":21}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],22:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":21}],24:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":21}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":21}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./German\":20,\"./Language\":21,\"./Norwegian\":22,\"./Pirate\":23,\"./Polish\":24,\"./Spanish\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":28,\"fs\":44}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":27,\"./FeatureParser\":28,\"./StepParser\":29}],31:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":44,\"yadda\":\"3V0FPO\"}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":28,\"fs\":44}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":31,\"./MochaPlugin\":32,\"./mocha/AsyncScenarioLevelPlugin\":34,\"./mocha/AsyncStepLevelPlugin\":35,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":27}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],39:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"__browserify_process\":47,\"fs\":44,\"path\":45}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":44,\"path\":45}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":44}],43:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],44:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],45:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":47,\"_shims\":43,\"util\":46}],46:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":43}],47:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.2.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.3.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.4.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        return subject.annotations && subject.annotations[language.localise('pending')];\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.5.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as os 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, iterator);\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, iterator);\n        });        \n    }  \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.6.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":37}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":26,\"fs\":42}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],28:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":42,\"yadda\":\"3V0FPO\"}],30:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":26,\"fs\":42}],31:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/SyncScenarioLevelPlugin\":35,\"./mocha/SyncStepLevelPlugin\":36}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        var parser = new FeatureFileParser(language);\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            console.log(step);\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });        \n    }     \n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"__browserify_process\":45,\"fs\":42,\"path\":43}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":42}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":42,\"path\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":42}],41:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],42:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],43:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":45,\"_shims\":41,\"util\":44}],44:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":41}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.7.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte|[Ff]ond)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given },\n        get majac() { return this.given },\n        get jezeli() { return this.when },\n        get jesli() { return this.when },\n        get gdy() { return this.when },\n        get kiedy() { return this.when },\n        get wtedy() { return this.then }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],29:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            console.log(step);\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });        \n    }     \n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.8.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.8 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given },\n        get majac() { return this.given },\n        get jezeli() { return this.when },\n        get jesli() { return this.when },\n        get gdy() { return this.when },\n        get kiedy() { return this.when },\n        get wtedy() { return this.then }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    function validate() {\n        if (scenarios.length == 0) throw new Error('Feature requires one or more scenarios');        \n    };    \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],29:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.feature;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            console.log(step);\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });        \n    }     \n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.10.9.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if \n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;    \n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":38}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};module.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;         \n    }\n\n    function is_node() {\n        return typeof module != 'undefined' &&\n               typeof module.exports != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    }\n\n}\n\n},{}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.10.9 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),    \n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":38}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given },\n        get majac() { return this.given },\n        get jezeli() { return this.when },\n        get jesli() { return this.when },\n        get gdy() { return this.when },\n        get kiedy() { return this.when },\n        get wtedy() { return this.then }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    } \n}\n\nmodule.exports = FeatureFileParser;\n},{\"./FeatureParser\":27,\"fs\":43}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, annotations, {});\n    };\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }; \n\n    var start_background = start_scenario;  \n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario,\n        background: start_background\n    }); \n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    };\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');        \n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};        \n        return scenario;\n    };\n\n    function validate() {\n        if (scenarios.length == 0) throw new Error('Feature requires one or more scenarios');        \n    };    \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,        \n        blank: end_description,\n        scenario: start_scenario\n    }); \n    var _this = this;  \n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function validate() {\n        if (steps.length == 0) throw new Error('Background requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers(); \n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };    \n}\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    };\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        };\n        return line;        \n    };\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],29:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n}\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":43,\"yadda\":\"3V0FPO\"}],31:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    if (options.deprecation_warning != false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details')        \n    }\n\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":27,\"fs\":43}],32:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() { \n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() { \n        return this.mocha\n    }\n}\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/SyncScenarioLevelPlugin\":36,\"./mocha/SyncStepLevelPlugin\":37}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {        \n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }    \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;          \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });        \n    }     \n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n        \n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator)\n        });\n    };\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });        \n    };\n\n    function describe(title, subject, iterator) {\n        var _describe = is_pending(subject) ? container.xdescribe : container.describe;\n        _describe(title, function() {\n            iterator(subject)\n        });        \n    }    \n\n    function it_async(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function(done) {\n            iterator(subject, done);\n        }) \n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = is_pending(subject) ? container.xit : container.it;\n        _it(title, function() {\n            iterator(subject);\n        }) \n    }  \n\n    function is_pending(subject) {\n        var regexp = new RegExp('^' + language.localise('pending') + '$');        \n        for (var key in subject.annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    }        \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;     \n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    var platform = new Platform();\n    var options = options || {};    \n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);                        \n        });        \n    } \n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });        \n    }     \n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        \n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":39,\"./phantom-path\":40,\"./phantom-process\":41,\"__browserify_process\":46,\"fs\":43,\"path\":44}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],42:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],43:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],44:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":46,\"_shims\":42,\"util\":45}],45:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":42}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.11.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":45}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.11.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":26,\"fs\":43}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":43,\"yadda\":undefined}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":26,\"fs\":43}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n    var abort;\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            abort = false;\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n    }\n\n    function step_async(step, iterator) {\n        base_plugin.it_async(step, step, function(step, done) {\n            if (abort) return done();\n            abort = true;\n            iterator(step, function(err) {\n                if (err) return done(err);\n                abort = false;\n                done();\n            });\n        });\n    }\n\n    function step_sync(step, iterator) {\n        base_plugin.it_sync(step, step, function(step) {\n            if (abort) return;\n            abort = true;\n            iterator(step);\n            abort = false;\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],39:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"_process\":45,\"fs\":43,\"path\":44}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],43:[function(require,module,exports){\n\n},{}],44:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":45}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":39}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-umd-0.11.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":41}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},__dirname=\"/\";/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n},{\"__browserify_process\":49}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.11.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":26,\"./parsers/index\":30,\"./plugins/index\":33,\"./shims/index\":41}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":21}],19:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":21}],20:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":21}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],22:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":21}],24:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":21}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":21}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":18,\"./French\":19,\"./German\":20,\"./Language\":21,\"./Norwegian\":22,\"./Pirate\":23,\"./Polish\":24,\"./Spanish\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":28,\"fs\":46}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":18}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":27,\"./FeatureParser\":28,\"./StepParser\":29}],31:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n},{\"fs\":46,\"yadda\":\"3V0FPO\"}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":18,\"../parsers/FeatureParser\":28,\"fs\":46}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":31,\"./MochaPlugin\":32,\"./mocha/AsyncScenarioLevelPlugin\":34,\"./mocha/AsyncStepLevelPlugin\":35,\"./mocha/ScenarioLevelPlugin\":37,\"./mocha/StepLevelPlugin\":38,\"./mocha/SyncScenarioLevelPlugin\":39,\"./mocha/SyncStepLevelPlugin\":40}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":18,\"../../parsers/FeatureFileParser\":27}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n    var abort;\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            abort = false;\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n    }\n\n    function step_async(step, iterator) {\n        base_plugin.it_async(step, step, function(step, done) {\n            if (abort) return done();\n            abort = true;\n            iterator(step, function(err) {\n                if (err) return done(err);\n                abort = false;\n                done();\n            });\n        });\n    }\n\n    function step_sync(step, iterator) {\n        base_plugin.it_sync(step, step, function(step) {\n            if (abort) return;\n            abort = true;\n            iterator(step);\n            abort = false;\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":36}],41:[function(require,module,exports){\nvar process=require(\"__browserify_process\");/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n},{\"../Platform\":12,\"./phantom-fs\":42,\"./phantom-path\":43,\"./phantom-process\":44,\"__browserify_process\":49,\"fs\":46,\"path\":47}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],45:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],46:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],47:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":49,\"_shims\":45,\"util\":48}],48:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":45}],49:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n;"
  },
  {
    "path": "dist/yadda-umd-0.11.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":45}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.11.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":26,\"fs\":43}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":43,\"yadda\":undefined}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":26,\"fs\":43}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],39:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"_process\":45,\"fs\":43,\"path\":44}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],43:[function(require,module,exports){\n\n},{}],44:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":45}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":39}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-umd-0.11.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":45}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.11.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":26,\"fs\":43}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.yadda(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":43,\"yadda\":undefined}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":26,\"fs\":43}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],39:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"_process\":45,\"fs\":43,\"path\":44}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],43:[function(require,module,exports){\n\n},{}],44:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":45}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":39}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-umd-0.11.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":39}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":45}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.11.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Spanish\":23}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":26,\"fs\":43}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":25,\"./FeatureParser\":26,\"./StepParser\":27}],29:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":43,\"yadda\":undefined}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":26,\"fs\":43}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":29,\"./MochaPlugin\":30,\"./mocha/AsyncScenarioLevelPlugin\":32,\"./mocha/AsyncStepLevelPlugin\":33,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36,\"./mocha/SyncScenarioLevelPlugin\":37,\"./mocha/SyncStepLevelPlugin\":38}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":25}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],39:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":40,\"./phantom-path\":41,\"./phantom-process\":42,\"_process\":45,\"fs\":43,\"path\":44}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":43,\"path\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":43}],43:[function(require,module,exports){\n\n},{}],44:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":45}],45:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":24,\"./parsers/index\":28,\"./plugins/index\":31,\"./shims/index\":39}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-umd-0.11.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":40}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":46}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.11.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":19}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Russian\":23,\"./Spanish\":24}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":27,\"fs\":44}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation/English\":16}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],29:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":26,\"./FeatureParser\":27,\"./StepParser\":28}],30:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":44,\"yadda\":undefined}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":27,\"fs\":44}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":30,\"./MochaPlugin\":31,\"./mocha/AsyncScenarioLevelPlugin\":33,\"./mocha/AsyncStepLevelPlugin\":34,\"./mocha/ScenarioLevelPlugin\":36,\"./mocha/StepLevelPlugin\":37,\"./mocha/SyncScenarioLevelPlugin\":38,\"./mocha/SyncStepLevelPlugin\":39}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation/English\":16,\"../../parsers/FeatureFileParser\":26}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":35}],40:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":41,\"./phantom-path\":42,\"./phantom-process\":43,\"_process\":46,\"fs\":44,\"path\":45}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":44,\"path\":45}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":44}],44:[function(require,module,exports){\n\n},{}],45:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":46}],46:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            var source = ev.source;\n            if ((source === window || source === null) && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":25,\"./parsers/index\":29,\"./plugins/index\":32,\"./shims/index\":40}]},{},[]);\n"
  },
  {
    "path": "dist/yadda-umd-0.11.6.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":4,\"./Dictionary\":5,\"./EventBus\":6,\"./FeatureFileSearch\":7,\"./FileSearch\":8,\"./Interpreter\":9,\"./Library\":11,\"./Platform\":13,\"./Yadda\":15,\"./localisation/index\":26,\"./parsers/index\":30,\"./plugins/index\":33,\"./shims/index\":41}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":2,\"./LevenshteinDistanceScore\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":2,\"./RegularExpression\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":2,\"./fn\":16}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":2,\"./shims/index\":41}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":2,\"./Competition\":3,\"./Context\":4,\"./EventBus\":6,\"./fn\":16}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":2,\"./Dictionary\":5,\"./Macro\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":4,\"./EventBus\":6,\"./RegularExpression\":14,\"./fn\":16}],13:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":47}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":2}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.11.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":4,\"./Interpreter\":9,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":2,\"../Library\":11}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Russian\":24,\"./Spanish\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":28,\"fs\":45}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: issue146,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function issue146() {\n        if (!FeatureParser.silence146) {\n            console.log(\"It appears that you are using background descriptions that either span\");\n            console.log(\"mutliple lines or begin immediately beneath the 'Background' keyword\");\n            console.log(\"We are considering removing this feature. Please update\");\n            console.log(\"https://github.com/acuminous/yadda/issues/146 if it is important to you\");\n            console.log(\"You can disable this message by setting FeatureParser.silence146 to true\");\n        }\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":2,\"../fn\":16,\"../localisation/English\":17}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":2}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":27,\"./FeatureParser\":28,\"./StepParser\":29}],31:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":45,\"yadda\":\"yadda\"}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":2,\"../localisation/English\":17,\"../parsers/FeatureParser\":28,\"fs\":45}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":31,\"./MochaPlugin\":32,\"./mocha/AsyncScenarioLevelPlugin\":34,\"./mocha/AsyncStepLevelPlugin\":35,\"./mocha/ScenarioLevelPlugin\":37,\"./mocha/StepLevelPlugin\":38,\"./mocha/SyncScenarioLevelPlugin\":39,\"./mocha/SyncStepLevelPlugin\":40}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"../../localisation/English\":17,\"../../parsers/FeatureFileParser\":27}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":36}],41:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":13,\"./phantom-fs\":42,\"./phantom-path\":43,\"./phantom-process\":44,\"_process\":47,\"fs\":45,\"path\":46}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":45}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":45,\"path\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":45}],45:[function(require,module,exports){\n\n},{}],46:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":47}],47:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}]},{},[1]);\n"
  },
  {
    "path": "dist/yadda-umd-0.11.7.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":4,\"./Dictionary\":5,\"./EventBus\":6,\"./FeatureFileSearch\":7,\"./FileSearch\":8,\"./Interpreter\":9,\"./Library\":11,\"./Platform\":13,\"./Yadda\":15,\"./localisation/index\":27,\"./parsers/index\":31,\"./plugins/index\":34,\"./shims/index\":42}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":2,\"./LevenshteinDistanceScore\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":2,\"./RegularExpression\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":2,\"./fn\":16}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":2,\"./shims/index\":42}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":2,\"./Competition\":3,\"./Context\":4,\"./EventBus\":6,\"./fn\":16}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":2,\"./Dictionary\":5,\"./Macro\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":4,\"./EventBus\":6,\"./RegularExpression\":14,\"./fn\":16}],13:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":2}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.11.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":4,\"./Interpreter\":9,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":2,\"../Library\":11}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue)',\n        then: '(?:[Ee]nt[aã]o)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Portuguese\":24,\"./Russian\":25,\"./Spanish\":26}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":29,\"fs\":46}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: issue146,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function issue146() {\n        if (!FeatureParser.silence146) {\n            console.log(\"It appears that you are using background descriptions that either span\");\n            console.log(\"mutliple lines or begin immediately beneath the 'Background' keyword\");\n            console.log(\"We are considering removing this feature. Please update\");\n            console.log(\"https://github.com/acuminous/yadda/issues/146 if it is important to you\");\n            console.log(\"You can disable this message by setting FeatureParser.silence146 to true\");\n        }\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":2,\"../fn\":16,\"../localisation/English\":17}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":2}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":28,\"./FeatureParser\":29,\"./StepParser\":30}],32:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* global describe, xdescribe, it, xit */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n    var feature;\n\n    if (options.deprecation_warning !== false) {\n        console.log('The MochaPlugin is deprecated as of 0.10.0 and will be removed in 0.12.0');\n        console.log('Replace it with one of AsyncScenarioLevelPlugin, SyncScenarioLevelPlugin, AsyncStepLevelPlugin or SyncStepLevelPlugin');\n        console.log('To disable this message use Yadda.plugins.mocha({deprecation_warning: false})');\n        console.log('See the readme for more details');\n    }\n\n    if (module.client) {\n        feature = function (text, next) {\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title, function() {\n                    next(feature);\n                });\n            });\n        };\n    } else {\n        feature = function (filenames, next) {\n            $(filenames).each(function(filename) {\n                var text = fs.readFileSync(filename, 'utf8');\n                parser.parse(text, function(feature) {\n                    var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                    _describe(feature.title || filename, function() {\n                        next(feature);\n                    });\n                });\n            });\n        };\n    }\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    }\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    }\n\n    if (typeof GLOBAL !== 'undefined') {\n        GLOBAL.features = GLOBAL.feature = feature;\n        GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.features = window.feature = feature;\n        window.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n    }\n};\n\n},{\"../Array\":2,\"../localisation/English\":17,\"../parsers/FeatureParser\":29,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    get mocha() {\n        var legacyPlugin = require('./MochaPlugin');\n        legacyPlugin.AsyncScenarioLevelPlugin = require('./mocha/AsyncScenarioLevelPlugin');\n        legacyPlugin.SyncScenarioLevelPlugin = require('./mocha/SyncScenarioLevelPlugin');\n        legacyPlugin.AsyncStepLevelPlugin = require('./mocha/AsyncStepLevelPlugin');\n        legacyPlugin.SyncStepLevelPlugin = require('./mocha/SyncStepLevelPlugin');\n        legacyPlugin.ScenarioLevelPlugin = require('./mocha/ScenarioLevelPlugin');\n        legacyPlugin.StepLevelPlugin = require('./mocha/StepLevelPlugin');\n        return legacyPlugin;\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":32,\"./MochaPlugin\":33,\"./mocha/AsyncScenarioLevelPlugin\":35,\"./mocha/AsyncStepLevelPlugin\":36,\"./mocha/ScenarioLevelPlugin\":38,\"./mocha/StepLevelPlugin\":39,\"./mocha/SyncScenarioLevelPlugin\":40,\"./mocha/SyncStepLevelPlugin\":41}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncScenarioLevelPlugin has been deprecated and will soon be removed.      *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_async(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* AsyncStepLevelPlugin has been deprecated and will soon be removed.          *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                iterator(step, function(err) {\n                    if (err) abort = true;\n                    done(err);\n                });\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar English = require('../../localisation/English');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || English;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"../../localisation/English\":17,\"../../parsers/FeatureFileParser\":28}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncScenarioLevelPlugin has been deprecated and will soon be removed.       *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.it_sync(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        if (!options.silenceDeprecations) {\n            console.log('*******************************************************************************');\n            console.log('* SyncStepLevelPlugin has been deprecated and will soon be removed.           *');\n            console.log('* Use the ScenarioLevelPlugin instead.                                        *');\n            console.log('* To turn off this message add silenceDeprecations: true to the init options. *');\n            console.log('*******************************************************************************');\n        }\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n        var abort;\n        $(steps).each(function(step) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        });\n    }\n\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":37}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":13,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}]},{},[1]);\n"
  },
  {
    "path": "dist/yadda-umd-0.12.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":4,\"./Dictionary\":5,\"./EventBus\":6,\"./FeatureFileSearch\":7,\"./FileSearch\":8,\"./Interpreter\":9,\"./Library\":11,\"./Platform\":13,\"./Yadda\":15,\"./localisation/index\":27,\"./parsers/index\":31,\"./plugins/index\":33,\"./shims/index\":37}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":2,\"./LevenshteinDistanceScore\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":2,\"./RegularExpression\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":2,\"./fn\":16}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":2,\"./shims/index\":37}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":2,\"./Competition\":3,\"./Context\":4,\"./EventBus\":6,\"./fn\":16}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":2,\"./Dictionary\":5,\"./Macro\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":4,\"./EventBus\":6,\"./RegularExpression\":14,\"./fn\":16}],13:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":43}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":2}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.12.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":4,\"./Interpreter\":9,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":2,\"../Library\":11}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue)',\n        then: '(?:[Ee]nt[aã]o)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Portuguese\":24,\"./Russian\":25,\"./Spanish\":26}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":29,\"fs\":41}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: issue146,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function issue146() {\n        if (!FeatureParser.silence146) {\n            console.log(\"It appears that you are using background descriptions that either span\");\n            console.log(\"mutliple lines or begin immediately beneath the 'Background' keyword\");\n            console.log(\"We are considering removing this feature. Please update\");\n            console.log(\"https://github.com/acuminous/yadda/issues/146 if it is important to you\");\n            console.log(\"You can disable this message by setting FeatureParser.silence146 to true\");\n        }\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":2,\"../fn\":16,\"../localisation\":27}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":2}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":28,\"./FeatureParser\":29,\"./StepParser\":30}],32:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":41,\"yadda\":\"yadda\"}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":32,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"../../localisation\":27,\"../../parsers/FeatureFileParser\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":2,\"../../Platform\":13,\"./BasePlugin\":34}],37:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":13,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"_process\":43,\"fs\":41,\"path\":42}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":41,\"path\":42}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":41}],41:[function(require,module,exports){\n\n},{}],42:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":43}],43:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}]},{},[1]);\n"
  },
  {
    "path": "dist/yadda-umd-0.12.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":15}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":15}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":36}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":15}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":15}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":42}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.12.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":15}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],17:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue)',\n        then: '(?:[Ee]nt[aã]o)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":19}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":19}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":19}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":16,\"./French\":17,\"./German\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Polish\":22,\"./Portuguese\":23,\"./Russian\":24,\"./Spanish\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":28,\"fs\":40}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n    var line;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations[annotation.key] = annotation.value;\n        annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, {});\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, {}, annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = {};\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations[annotation.key] = annotation.value;\n        stashed_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    }\n\n    function capture_description(event, text) {\n        description.push(text);\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = {};\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: issue146,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function issue146() {\n        if (!FeatureParser.silence146) {\n            console.log(\"It appears that you are using background descriptions that either span\");\n            console.log(\"mutliple lines or begin immediately beneath the 'Background' keyword\");\n            console.log(\"We are considering removing this feature. Please update\");\n            console.log(\"https://github.com/acuminous/yadda/issues/146 if it is important to you\");\n            console.log(\"You can disable this message by setting FeatureParser.silence146 to true\");\n        }\n    }\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    }\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        });\n        examples.push(example);\n    }\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: shallowClone(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallowClone(source) {\n        var dest = {};\n        for (var key in source) {\n            dest[key] = source[key];\n        }\n        return dest;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../fn\":15,\"../localisation\":26}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":27,\"./FeatureParser\":28,\"./StepParser\":29}],31:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":40,\"yadda\":\"yadda\"}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":31,\"./mocha/ScenarioLevelPlugin\":34,\"./mocha/StepLevelPlugin\":35}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":26,\"../../parsers/FeatureFileParser\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(step, done) {\n                if (abort) return done();\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(step) {\n                if (abort) return;\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":33}],36:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":37,\"./phantom-path\":38,\"./phantom-process\":39,\"_process\":42,\"fs\":40,\"path\":41}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":40}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":40,\"path\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":40}],40:[function(require,module,exports){\n\n},{}],41:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":42}],42:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":14,\"./localisation/index\":26,\"./parsers/index\":30,\"./plugins/index\":32,\"./shims/index\":36}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.13.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":16}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":16}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":16}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":43}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.13.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Portuguese\":24,\"./Russian\":25,\"./Spanish\":26}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":29,\"fs\":41}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1]);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (index + 1) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.get = function(key) {\n        return annotations[key.toLowerCase()];\n    };\n\n    this.remove = function(key) {\n        delete annotations[key.toLowerCase];\n    };\n\n    this.merge = function(other) {\n        other.each(function(key, value) {\n            annotations[key] = value;\n        });\n        return this;\n    };\n\n    this.each = function(iterator) {\n        for (var key in annotations) {\n            iterator(key, annotations[key]);\n        }\n    };\n\n    this.keys = function() {\n        var result = [];\n        for (var key in annotations) {\n            result.push(key);\n        }\n        return result;\n    };\n\n    this.isEmpty = function() {\n        return this.keys().length === 0;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        headings = split(data).collect(function(column) {\n            return { text: StringUtils.trim(column), indentation: StringUtils.indentation(column) };\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n    }\n\n    function continue_capturing_multiline_fields(event, data) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: example.annotations.merge(scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":16,\"../localisation\":27}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":28,\"./FeatureParser\":29,\"./StepParser\":30}],32:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":41,\"yadda\":\"yadda\"}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":32,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$');\n        return $(annotations && annotations.keys()).find(function(key) {\n            return regexp.test(key);\n        });\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":27,\"../../parsers/FeatureFileParser\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"_process\":43,\"fs\":41,\"path\":42}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":41,\"path\":42}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":41}],41:[function(require,module,exports){\n\n},{}],42:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":43}],43:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./localisation/index\":27,\"./parsers/index\":31,\"./plugins/index\":33,\"./shims/index\":37}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.13.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":16}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (var key in terms) {\n            callback(key, terms[key]);\n        }\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            term = term.replace(prefix + sub_term, sub_term_definition);\n            return term;\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    };\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    };\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    };\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":16}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":37}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":16}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    };\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    };\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":16}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":43}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.13.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":20}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":20}],19:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":20}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":20}],23:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":20}],24:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":20}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":20}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":20}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":17,\"./French\":18,\"./German\":19,\"./Language\":20,\"./Norwegian\":21,\"./Pirate\":22,\"./Polish\":23,\"./Portuguese\":24,\"./Russian\":25,\"./Spanish\":26}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":29,\"fs\":41}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1]);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (index + 1) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        headings = split(data).collect(function(column) {\n            return { text: StringUtils.trim(column), indentation: StringUtils.indentation(column) };\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n    }\n\n    function continue_capturing_multiline_fields(event, data) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":16,\"../localisation\":27}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":28,\"./FeatureParser\":29,\"./StepParser\":30}],32:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":41,\"yadda\":\"yadda\"}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":32,\"./mocha/ScenarioLevelPlugin\":35,\"./mocha/StepLevelPlugin\":36}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":27,\"../../parsers/FeatureFileParser\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":34}],37:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":38,\"./phantom-path\":39,\"./phantom-process\":40,\"_process\":43,\"fs\":41,\"path\":42}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":41,\"path\":42}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":41}],41:[function(require,module,exports){\n\n},{}],42:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":43}],43:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./localisation/index\":27,\"./parsers/index\":31,\"./plugins/index\":33,\"./shims/index\":37}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.14.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (this.is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (is_expandable(pattern) && converters) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && count_matching_groups(pattern) !== $(converters).length) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return !!definitions[term];\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return _this.is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                              : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        args.collect_async(function(arg, index, callback) {\n            parsed_signature.converters[index](arg, callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.14.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1]);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (index + 1) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        headings = split(data).collect(function(column) {\n            return { text: StringUtils.trim(column), indentation: StringUtils.indentation(column) };\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n    }\n\n    function continue_capturing_multiline_fields(event, data) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.14.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.14.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1]);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (index + 1) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation) {\n        validate();\n        return feature.on(event, annotation);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    }\n\n    function start_examples(event, data) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        headings = split(data).collect(function(column) {\n            return { text: StringUtils.trim(column), indentation: StringUtils.indentation(column) };\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n    }\n\n    function continue_capturing_multiline_fields(event, data) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.14.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.14.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank', line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var examples;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text) {\n        steps.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        /* jslint boss: true */\n        return examples = new Examples(_this);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.15.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, ' ');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, ' ');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: capture_headings,\n        blank: fn.noop,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.unregister('dash');\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', start_scenario);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.15.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":21}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":21}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":42}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":21}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":21}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":48}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":21}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, new Date(value));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    return next(null, parseFloat(value));\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./pass-through-converter\":20}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    return next(null, parseInt(value));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":25}],23:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":25}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":25}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],26:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":25}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":25}],28:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":25}],29:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":25}],30:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":25}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":25}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":22,\"./French\":23,\"./German\":24,\"./Language\":25,\"./Norwegian\":26,\"./Pirate\":27,\"./Polish\":28,\"./Portuguese\":29,\"./Russian\":30,\"./Spanish\":31}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":34,\"fs\":46}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, ' ');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, ' ');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":21,\"../localisation\":32}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],36:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":33,\"./FeatureParser\":34,\"./StepParser\":35}],37:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":46,\"yadda\":\"yadda\"}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":37,\"./mocha/ScenarioLevelPlugin\":40,\"./mocha/StepLevelPlugin\":41}],39:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":32,\"../../parsers/FeatureFileParser\":33}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":39}],42:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":43,\"./phantom-path\":44,\"./phantom-process\":45,\"_process\":48,\"fs\":46,\"path\":47}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":46}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":46,\"path\":47}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":46}],46:[function(require,module,exports){\n\n},{}],47:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":48}],48:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":32,\"./parsers/index\":36,\"./plugins/index\":38,\"./shims/index\":42}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.15.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":44}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":50}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":48}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":48,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":41}],44:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":45,\"./phantom-path\":46,\"./phantom-process\":47,\"_process\":50,\"fs\":48,\"path\":49}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":48}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":48,\"path\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":48}],48:[function(require,module,exports){\n\n},{}],49:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":50}],50:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":44}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.15.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":44}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":50}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":48}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":48,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":41}],44:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":45,\"./phantom-path\":46,\"./phantom-process\":47,\"_process\":50,\"fs\":48,\"path\":49}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":48}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":48,\"path\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":48}],48:[function(require,module,exports){\n\n},{}],49:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":50}],50:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":44}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.15.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":45}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":51}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":49}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":49,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, iterator);\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],45:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":46,\"./phantom-path\":47,\"./phantom-process\":48,\"_process\":51,\"fs\":49,\"path\":50}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":49,\"path\":50}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":49}],49:[function(require,module,exports){\n\n},{}],50:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":51}],51:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":45}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.15.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":45}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":51}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.15.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":49}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":49,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],45:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":46,\"./phantom-path\":47,\"./phantom-process\":48,\"_process\":51,\"fs\":49,\"path\":50}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":49,\"path\":50}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":49}],49:[function(require,module,exports){\n\n},{}],50:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":51}],51:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":45}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.16.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":45}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return converter.bind.apply(converter, [null].concat(args.slice(index, index += converter.length - 1)));\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":51}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.16.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":49}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":49,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],45:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":46,\"./phantom-path\":47,\"./phantom-process\":48,\"_process\":51,\"fs\":49,\"path\":50}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":49,\"path\":50}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":49}],49:[function(require,module,exports){\n\n},{}],50:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":51}],51:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":45}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.16.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":23}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":13,\"./converters/pass-through-converter\":21}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":23}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":45}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":23}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":13,\"./fn\":23}],12:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":51}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.16.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":23}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":16,\"./float-converter\":17,\"./integer-converter\":19,\"./list-converter\":20,\"./pass-through-converter\":21,\"./table-converter\":22}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":14}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":10}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":49}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":14,\"../fn\":23,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":49,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":12,\"./BasePlugin\":42}],45:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":12,\"./phantom-fs\":46,\"./phantom-path\":47,\"./phantom-process\":48,\"_process\":51,\"fs\":49,\"path\":50}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":49}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":49,\"path\":50}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":49}],49:[function(require,module,exports){\n\n},{}],50:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":51}],51:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            currentQueue[queueIndex].run();\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Platform\":12,\"./Yadda\":15,\"./converters/index\":18,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":45}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.16.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":44,\"./scores/MultiScore\":45,\"./scores/SameLibraryScore\":46}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":47}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":53}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.16.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":27}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":23,\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":51}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":51,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        this.scores.find(fn.curry(null, lesserScore, other));\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function lesserScore(other, score, index) {\n        return score.value > other.scores[index].value;\n    }\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.value > other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],47:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./phantom-fs\":48,\"./phantom-path\":49,\"./phantom-process\":50,\"_process\":53,\"fs\":51,\"path\":52}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":51}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":51,\"path\":52}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":51}],51:[function(require,module,exports){\n\n},{}],52:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":53}],53:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":47}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.16.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":44,\"./scores/MultiScore\":45,\"./scores/SameLibraryScore\":46}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":47}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":53}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.16.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":27}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":23,\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":51}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":51,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],47:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./phantom-fs\":48,\"./phantom-path\":49,\"./phantom-process\":50,\"_process\":53,\"fs\":51,\"path\":52}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":51}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":51,\"path\":52}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":51}],51:[function(require,module,exports){\n\n},{}],52:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":53}],53:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":47}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":44,\"./scores/MultiScore\":45,\"./scores/SameLibraryScore\":46}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":47}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":53}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":27}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":27}],25:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":27}],26:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":27}],27:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":27}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":27}],30:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":27}],31:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":27}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":27}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":27}],34:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Dutch\":23,\"./English\":24,\"./French\":25,\"./German\":26,\"./Language\":27,\"./Norwegian\":28,\"./Pirate\":29,\"./Polish\":30,\"./Portuguese\":31,\"./Russian\":32,\"./Spanish\":33}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":36,\"fs\":51}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":34}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],38:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":35,\"./FeatureParser\":36,\"./StepParser\":37}],39:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":51,\"yadda\":\"yadda\"}],40:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":39,\"./mocha/ScenarioLevelPlugin\":42,\"./mocha/StepLevelPlugin\":43}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":34,\"../../parsers/FeatureFileParser\":35}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":41}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],47:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./phantom-fs\":48,\"./phantom-path\":49,\"./phantom-process\":50,\"_process\":53,\"fs\":51,\"path\":52}],48:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":51}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":51,\"path\":52}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":51}],51:[function(require,module,exports){\n\n},{}],52:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":53}],53:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":34,\"./parsers/index\":38,\"./plugins/index\":40,\"./shims/index\":47}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":54}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    // Requiring fs locally so it doesn't break component\n    var fs = require('fs');\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"./FeatureParser\":37,\"fs\":52}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"fs\":52,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function() {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./phantom-fs\":49,\"./phantom-path\":50,\"./phantom-process\":51,\"_process\":54,\"fs\":52,\"path\":53}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":52}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":52,\"path\":53}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":52}],52:[function(require,module,exports){\n\n},{}],53:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":54}],54:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.10.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.10 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(language) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(language);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(language) {\n\n    /* jslint shadow: true */\n    var language = language || Localisation.default;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n};\n\nvar Handlers = function(handlers) {\n\n    /* jslint shadow: true */\n    var handlers = handlers || {};\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function() {\n        $(Array.prototype.slice.call(arguments)).each(function(event) {\n            delete handlers[event];\n        });\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario,\n        background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n        /* jslint boss: true */\n        return feature = new Feature(title, annotations, new Annotations());\n    }\n\n    function start_scenario(event, title, line_number) {\n        feature = new Feature(title, new Annotations(), annotations);\n        return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function(event, data, line_number) {\n        current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.stash = function(key, value) {\n        if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n        annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function() {\n        return annotations;\n    };\n};\n\nvar Feature = function(title, annotations, stashed_annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,\n        annotation: stash_annotation,\n        scenario: start_scenario,\n        background: start_background\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n        background = new Background(title, _this);\n        stashed_annotations = new Annotations();\n        return background;\n    }\n\n    function stash_annotation(event, annotation) {\n        handlers.unregister('background');\n        stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n        description.push(StringUtils.trim(text));\n    }\n\n    function end_description(event, text, line_number) {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    }\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, background, stashed_annotations, _this);\n        scenarios.push(scenario);\n        stashed_annotations = new Annotations();\n        return scenario;\n    }\n\n    function validate() {\n        if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };\n    };\n};\n\nvar Background = function(title, feature) {\n\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: stash_annotation,\n        scenario: start_scenario\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', stash_annotation);\n        handlers.register('scenario', start_scenario);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        validate();\n        return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        return {\n            steps: steps\n        };\n    };\n};\n\nvar NullBackground = function() {\n    var handlers = new Handlers();\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        return {\n            steps: []\n        };\n    };\n};\n\nvar Scenario = function(title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n        text: capture_step,\n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n        handlers.register('dash', enable_multiline_step);\n        steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n        handlers.register('text', start_multiline_step);\n        handlers.register('blank', stash_blanks);\n        indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n        handlers.register('dash', disable_multiline_step);\n        handlers.register('text', continue_multiline_step);\n        handlers.register('blank', stash_blanks);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n        handlers.register('examples', start_examples);\n        append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n        unstash_blanks();\n        append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n        blanks.push(text);\n    }\n\n    function unstash_blanks() {\n        if (!blanks.length) return;\n        append_to_step(blanks.join('\\n'), '\\n');\n        blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n        handlers.unregister('dash');\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n        unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n        if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n        steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n        validate();\n        examples = new Examples(_this);\n        return examples;\n    }\n\n    function validate() {\n        if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations.export(),\n            description: description,\n            steps: background.export().steps.concat(steps)\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n        blank: fn.noop,\n        dash: start_example_table,\n        text: capture_headings\n    });\n    var _this = this;\n\n    function start_example_table(evnet, data, line_number) {\n        handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n        handlers.register('annotation', stash_annotation);\n        handlers.register('text', capture_singleline_fields);\n        handlers.register('dash', enable_multiline_examples);\n        var pos = 1;\n        headings = split(data).collect(function(column) {\n            var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n            pos += column.length + 1;\n            return attributes;\n        }).naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n        handlers.unregister('blank', 'dash');\n        annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n        handlers.register('dash', end_example_table);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n        annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', continue_capturing_multiline_fields);\n        handlers.register('dash', stop_capturing_multiline_fields);\n        handlers.register('blank', end_example_table);\n        examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n        add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n        parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n        handlers.register('text', start_capturing_multiline_fields);\n        annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n        handlers.unregister('text', 'dash');\n        handlers.register('blank', fn.noop);\n        handlers.register('annotation', start_scenario);\n        handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n        var fields = examples.last().fields;\n        $(headings).each(function(heading) {\n            fields[heading.text + '.index'] = [ examples.length ];\n            fields[heading.text + '.start.line'] = [ line_number ];\n            fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n        });\n    }\n\n    function parse_fields(row, fields) {\n        split(row, headings.length).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n        return fields;\n    }\n\n    function split(row, number_of_fields) {\n        var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n        var fields = $(row.split(separator));\n        if (number_of_fields !== undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n        }\n        return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n        validate();\n        return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n        if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function(event, data, line_number) {\n        return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example.fields, scenario.title),\n                annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                description: substitute_all(example, scenario.description),\n                steps: substitute_all(example.fields, scenario.steps)\n            };\n        }).naked();\n    };\n\n    function shallow_merge() {\n        var result = {};\n        $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n            for (var key in annotations) {\n                result[key] = annotations[key];\n            }\n        });\n        return result;\n    }\n\n    function substitute_all(example, lines) {\n        return $(lines).collect(function(line) {\n            return substitute(example, line);\n        }).naked();\n    }\n\n    function substitute(example, line) {\n        for (var heading in example) {\n            line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n        }\n        return line;\n    }\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.3.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.isLanguage = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.isLanguage ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.4.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            fn.invoke(macro, context.properties, args.concat(next));\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.5.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.6.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort( by_ascending_score );\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.beats(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.beats = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference > 0;\n        }\n        return false;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return !this.scores.find(fn.curry(null, differentScore, other));\n    };\n\n    function differentScore(other, score, index) {\n        return score.value !== other.scores[index].value;\n    }\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.beats = function(other) {\n        return this.compare(other) > 0;\n    };\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.7.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.8.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.8 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.17.9.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result = fn.invoke(macro, context.properties, args.concat(next));\n            if (is_promise(result)) return result.then(function() {\n                next();\n            });\n            if (is_async(args, next)) return next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        return result && result.then;\n    }\n\n    function is_async(args, next) {\n        return macro.length === args.length && next;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof GLOBAL != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.17.9 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_node()) return shims.node();\n        if (platform.is_browser())\n            if (platform.is_karma()) return shims.karma();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.18.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.18.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.19.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.19.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    context.skip && context.skip();\n                    return done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.20.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = [];\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err, result) {\n                if (err) return each_callback(err);\n                results.push(result);\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            return converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.20.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.21.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                return next && next(err)\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.21.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.22.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err)\n                throw err\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.22.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return done(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = setTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.22.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score)\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err)\n                throw err\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.22.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn()\n        }\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri)\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function () {\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: false */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.22.2.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 0.22.2 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-0.3.0.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fnUtils = require('./fnUtils');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var before = fnUtils.NO_OP;\n    var after = fnUtils.NO_OP;\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        run(script, environment.merge(ctx));        \n    };\n\n    var run = function(script, env) {\n        fnUtils.invoke(before, env.ctx);\n        try {\n            _this.interpreter.interpret(script, env.ctx);\n        } finally {\n            fnUtils.invoke(after, env.ctx);\n        }        \n    }\n\n    this.before = function(fn) {\n        before = fn;\n        return this;\n    };\n\n    this.after = function(fn) {\n        after = fn;\n        return this;\n    };\n\n    this.toString = function() {\n        \"Yadda 0.3.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fnUtils\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx) {\n        $(scenario).each(function(step) { \n            _this.interpret_step(step, ctx);\n        });\n    };\n\n    this.interpret_step = function(step, ctx) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin')\n}\n},{\"./CasperPlugin\":17}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    function curry(ctx, fn) {\n        var slice = Array.prototype.slice;\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    } ;\n\n    return {\n        NO_OP: function() {},\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],17:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":18,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fnUtils = require('./fnUtils');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fnUtils.curry(array, in_array, array);\n        array.each = fnUtils.curry(array, each, array);\n        array.collect = fnUtils.curry(array, collect, array);\n        array.flatten = fnUtils.curry(array, flatten, array);\n        array.inject = fnUtils.curry(array, inject, array);\n        array.push_all = fnUtils.curry(array, push_all, array);\n        array.find_all = fnUtils.curry(array, find_all, array);\n        array.find = fnUtils.curry(array, find, array);\n        array.naked = fnUtils.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, fn) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = fn(items[i]);\n        };\n        return result;\n    };\n\n    function collect(items, fn) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(fn(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, fn) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = fn(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fnUtils\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fnUtils = require('./fnUtils');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, fn, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var fn = fn || fnUtils.NO_OP;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step);\n        return fnUtils.invoke(fn, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fnUtils\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios = [];\n\n    this.parse = function(text) {\n        current_scenario = {};\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}]},{},[\"gUiUAT\"])(gUiUAT)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.4.0.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        \"Yadda 0.4.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Array\":11,\"./Dictionary\":4}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin')\n}\n},{\"./CasperPlugin\":17}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":18,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback);        \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios = [];\n\n    this.parse = function(text) {\n        current_scenario = {};\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}]},{},[\"gUiUAT\"])(gUiUAT)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.4.1.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        \"Yadda 0.4.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin'),\n    MochaPlugin: require('./MochaPlugin'),\n    JasminePlugin: require('./MochaPlugin')\n}\n},{\"./MochaPlugin\":17,\"./CasperPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],18:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios = [];\n\n    this.parse = function(text) {\n        current_scenario = {};\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],17:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(yadda, feature, filename) {\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(feature, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };        \n    };\n\n    return {\n        feature: feature\n    };\n};\n},{\"fs\":19,\"../parsers/TextParser\":16}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])(gUiUAT)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.4.2.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Interpreter\":1,\"./Yadda\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":8,\"./fn\":9,\"./Array\":10}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        \"Yadda 0.4.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":1,\"./Environment\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":10,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin'),\n    MochaPlugin: require('./MochaPlugin'),\n    JasminePlugin: require('./MochaPlugin')\n}\n},{\"./MochaPlugin\":17,\"./CasperPlugin\":18}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],18:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":11,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":10}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":10}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":10}],17:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(yadda, feature, filename) {\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(feature, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };        \n    };\n\n    return {\n        feature: feature\n    };\n};\n},{\"fs\":19,\"../parsers/TextParser\":16}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":10,\"../localisation\":5}]},{},[\"gUiUAT\"])(gUiUAT)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.4.3.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    CasperPlugin: require('./CasperPlugin'),\n    MochaPlugin: require('./MochaPlugin'),\n    JasminePlugin: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":17,\"./MochaPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nvar CasperPlugin = function(yadda, casper) {\n\n    this.init = function() {\n\n        yadda.interpreter.interpret_step = function(step, ctx) {\n            var _this = this;\n            casper.then(function() {\n                casper.test.info(step);\n                _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n            });  \n        };\n\n        casper.yadda = function(script, ctx) {\n            if (script == undefined) return this;\n            yadda.yadda(script, ctx);\n        }\n\n        return casper;\n    };\n};\n\nmodule.exports = CasperPlugin;\n\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],18:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = (function() {\n\n    function MochaPlugin(options) {\n\n        var options = options || {};\n        var parser = options.parser || new TextParser();\n        var mode = options.mode || 'async';\n\n        this.upgrade = function(Yadda) {\n\n            function feature(name, filename) {\n\n                var yadda = this;\n\n                var runners = {\n                    async: runAsyncScenario,\n                    asynchronous: runAsyncScenario,\n                    sync: runSyncScenario,\n                    synchronous: runSyncScenario\n                };\n\n                describe(name, function() {            \n                    var text = fs.readFileSync(filename, 'utf8');\n                    try {\n                        var scenarios = parser.parse(text);\n                        runScenarios(scenarios);\n                    } catch (e) {\n                        throw new Error(e);\n                    }                 \n                });\n\n                function runScenarios(scenarios) {\n                    var runner = runners[mode];\n                    if (!runner) throw 'Unsupported mode: ' + mode; \n                    for (var i = 0; i < scenarios.length; i++) {\n                        runner(scenarios[i]);\n                    };       \n                };      \n\n                function runAsyncScenario(scenario) {\n                    it(scenario.title, function(done) {\n                        yadda.yadda(scenario.steps, done);\n                    });\n                };\n\n                function runSyncScenario(scenario) {\n                    it(scenario.title, function() {\n                        yadda.yadda(scenario.steps);\n                    });\n                };\n            };\n\n            Yadda.prototype.mocha = feature;\n            Yadda.prototype.jasmine = feature;\n        };\n    };\n\n    return MochaPlugin;\n})();\n},{\"fs\":19,\"../parsers/TextParser\":16}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])(gUiUAT)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.4.4.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;    \n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;            \n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);          \n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };   \n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":17,\"./MochaPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)$/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)$/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };            \n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],18:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"fs\":19,\"../parsers/TextParser\":16,\"../Yadda\":1}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])(gUiUAT)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.4.5.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":17,\"./MochaPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    }\n};\n\nmodule.exports = TextParser;\n},{\"../Array\":11}],18:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"fs\":19,\"../parsers/TextParser\":16,\"../Yadda\":1}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])(gUiUAT)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.4.6.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({\"yadda\":[function(require,module,exports){\nmodule.exports=require('gUiUAT');\n},{}],\"gUiUAT\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Yadda\":1,\"./Interpreter\":2,\"./Library\":3,\"./Dictionary\":4,\"./localisation/index\":5,\"./parsers/index\":6,\"./plugins/index\":7}],1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Interpreter\":2,\"./Environment\":8,\"./fn\":9}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Competition\":10,\"./Array\":11,\"./fn\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Macro\":12,\"./Dictionary\":4,\"./Array\":11}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":11,\"./RegularExpression\":13}],5:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],6:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],7:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":17,\"./MochaPlugin\":18}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],17:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./LevenshteinDistanceScore\":20,\"./Array\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":9}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./fn\":9,\"./Environment\":8,\"./RegularExpression\":13}],13:[function(require,module,exports){\n(function(){/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n})()\n},{\"./Array\":11}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Library\":3,\"../Array\":11}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":11}],18:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"fs\":19,\"../parsers/TextParser\":16,\"../Yadda\":1}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Library\":3,\"../Array\":11,\"../localisation\":5}]},{},[\"gUiUAT\"])(gUiUAT)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.4.7.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":11}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":6}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":9}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./fn\":11}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":3,\"./Macro\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Environment\":4,\"./RegularExpression\":9,\"./fn\":11}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.4.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":4,\"./Interpreter\":5,\"./fn\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Dictionary\":3,\"./Interpreter\":5,\"./Library\":7,\"./Yadda\":10,\"./localisation/index\":15,\"./parsers/index\":17,\"./plugins/index\":20}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":7}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":7,\"../localisation\":15}],15:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":13,\"./Pirate\":14}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return scenarios;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],17:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],18:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var scenarios = parser.parse(text);\n                runScenarios(scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"../Yadda\":10,\"../parsers/TextParser\":16,\"fs\":21}],20:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":18,\"./MochaPlugin\":19}],21:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.5.0.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = [];\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":11}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":6}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":9}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        if (!next) iterator = fn.asynchronize(null, iterator);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    this.interpret_step = function(step, ctx, callback) {\n        this.rank_macros(step).clear_winner().interpret(step, ctx, callback);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n}\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./fn\":11}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":3,\"./Macro\":8}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, callback) {    \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step).concat(callback); \n        return fn.invoke(macro, env.ctx, args);\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Environment\":4,\"./RegularExpression\":9,\"./fn\":11}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() interface to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.5.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":4,\"./Interpreter\":5,\"./fn\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),    \n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Dictionary\":3,\"./Interpreter\":5,\"./Library\":7,\"./Yadda\":10,\"./localisation/index\":15,\"./parsers/index\":17,\"./plugins/index\":20}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":7}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":7,\"../localisation\":15}],15:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":13,\"./Pirate\":14}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return {title: current_feature, scenarios: scenarios};\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],17:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":16}],18:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    yadda.interpreter.interpret_step = function(step, ctx) {\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            _this.rank_macros(step).clear_winner().interpret(step, ctx);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{}],19:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var feature = parser.parse(text);\n                runScenarios(feature.scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"../Yadda\":10,\"../parsers/TextParser\":16,\"fs\":21}],20:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":18,\"./MochaPlugin\":19}],21:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.5.1.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n\tvar event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n    \tif (arguments.length == 1) return this.send(event_name, {});\n    \tif (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);    \t\n        notify_handlers(event_name, event_data);\n    \tnext && next();        \n    \treturn this;\n    };\n\n \tthis.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n \t};\n\n \tvar notify_handlers = function(event_name, event_data) {\n\t\tfind_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n \t};\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    }; \t\n};\n\nfunction instance() {\n\treturn event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: ctx });        \n        var iterator = make_step_iterator(ctx, next);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    var make_step_iterator = function(ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, ctx, next) {\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n        _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":3,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, next) {   \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: ctx, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, env.ctx, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Environment\":4,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    this.interpret = this.yadda;\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.5.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":4,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Dictionary\":3,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return {title: current_feature, scenarios: scenarios};\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var feature = parser.parse(text);\n                runScenarios(feature.scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.5.2.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.eachAsync = fn.curry(array, eachAsync, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function eachAsync(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands a macros execution context\nvar Environment = function(ctx) {\n\n    this.ctx = {};\n    this._merge_on = 'ctx';\n\n    this.merge = function(other) {\n        other = get_item_to_merge(other);\n        return new Environment(this.ctx)._merge(other);\n    };\n\n    var get_item_to_merge = function(other) {\n        if (!other) return {};\n        return other._merge_on ? other[other._merge_on] : other;\n    };\n\n    this._merge = function(other_ctx) {\n        for (var key in other_ctx) { this.ctx[key] = other_ctx[key] }; \n        return this;\n    };\n\n    this._merge(ctx);\n};\n\nmodule.exports = Environment;\n},{}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n\tvar event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n    \tif (arguments.length == 1) return this.send(event_name, {});\n    \tif (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);    \t\n        notify_handlers(event_name, event_data);\n    \tnext && next();        \n    \treturn this;\n    };\n\n \tthis.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n \t};\n\n \tvar notify_handlers = function(event_name, event_data) {\n\t\tfind_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n \t};\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    }; \t\n};\n\nfunction instance() {\n\treturn event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, ctx, next) {\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: ctx });        \n        var iterator = make_step_iterator(ctx, next);\n        $(scenario).eachAsync(iterator, next);\n    };\n\n    var make_step_iterator = function(ctx, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, ctx, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, ctx, next) {\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n        _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, ctx) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, ctx);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, ctx) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, ctx));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":3,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Environment = require('./Environment');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, ctx) {    \n    \n    var environment = new Environment(ctx);\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, ctx, next) {   \n        var env = environment.merge(ctx);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: ctx, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, env.ctx, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Environment\":4,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Environment = require('./Environment');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, ctx) {\n\n    this.interpreter = new Interpreter(libraries);\n    var environment = new Environment(ctx);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(script, ctx, next) {\n        if (script == undefined) return this;\n        if (arguments.length == 2 && fn.is_function(ctx)) {\n            next = ctx;\n            ctx = undefined;\n        };\n        run(script, environment.merge(ctx), next);\n    };\n\n    this.interpret = this.yadda;\n\n    var run = function(script, env, next) {\n        _this.interpreter.interpret(script, env.ctx, next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.5.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Environment\":4,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Dictionary\":3,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\tvar annotations;\n\n    this.parse = function(text) {\n        current_scenario = {};\n        current_feature = null;\n\t\tannotations = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        return {title: current_feature, scenarios: scenarios, annotations: annotations};\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n\t\tif (match = ANNOTATION_REGEX.exec(line)) {\n\t\t\tannotations[match[1]] = match[2];\n\t\t} else if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature != null) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar TextParser = require('../parsers/TextParser');\nvar Yadda = require('../Yadda');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(name, filename) {\n\n        var yadda = this;\n\n        var runners = {\n            async: runAsyncScenario,\n            asynchronous: runAsyncScenario,\n            sync: runSyncScenario,\n            synchronous: runSyncScenario\n        };\n\n        describe(name, function() {            \n            var text = fs.readFileSync(filename, 'utf8');\n            try {\n                var feature = parser.parse(text);\n                runScenarios(feature.scenarios);\n            } catch (e) {\n                throw new Error(e);\n            }                 \n        });\n\n        function runScenarios(scenarios) {\n            var runner = runners[mode];\n            if (!runner) throw 'Unsupported mode: ' + mode; \n            for (var i = 0; i < scenarios.length; i++) {\n                runner(scenarios[i]);\n            };       \n        };      \n\n        function runAsyncScenario(scenario) {\n            it(scenario.title, function(done) {\n                yadda.yadda(scenario.steps, done);\n            });\n        };\n\n        function runSyncScenario(scenario) {\n            it(scenario.title, function() {\n                yadda.yadda(scenario.steps);\n            });\n        };\n    };\n\n    Yadda.prototype.mocha = feature;\n    Yadda.prototype.jasmine = feature;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.6.0.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw 'Undefined Step: [' + step + ']';\n        if (joint_first_place()) throw 'Ambiguous Step: [' + step + ']';\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw 'Duplicate definition: [' + term + ']';\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw 'Circular Definition: \\[' + already_expanding.join(', ') + '\\]'; \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context});        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw 'Duplicate macro: [' + signature + ']';\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        current_scenario = { steps: [] };\n        current_feature = null;\n\t\tannotations = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        var result = {title: current_feature, scenarios: scenarios, annotations: annotations};\n        return next && next(result) || result;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n\t\tif (match = ANNOTATION_REGEX.exec(line)) {\n\t\t\tannotations[match[1]] = match[2];\n\t\t} else if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature) throw \"You can only specify a single feature\";\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            describe(feature.title || filename, function() {         \n                next(feature);\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.6.1.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]'); \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var current_feature;\n    var current_scenario;\n    var scenarios;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        current_scenario = { steps: [] };\n        current_feature = null;\n\t\tannotations = {};\n        scenarios = [];\n        split(text).each(function(line) {\n            parse_line(line);\n        });\n        var result = {title: current_feature, scenarios: scenarios, annotations: annotations};\n        return next && next(result) || result;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n\t\tif (match = ANNOTATION_REGEX.exec(line)) {\n\t\t\tannotations[match[1]] = match[2];\n\t\t} else if (match = FEATURE_REGEX.exec(line)) {\n            if (current_feature) throw new Error(\"You can only specify a single feature\");\n            current_feature = match[1];\n        } else if (match = SCENARIO_REGEX.exec(line)) {\n            current_scenario = { title: match[1], steps: [] };\n            scenarios.push(current_scenario);\n        } else if (match = STEP_REGEX.exec(line)) {\n            current_scenario.steps.push(match[1]);\n        }\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            describe(feature.title || filename, function() {         \n                next(feature);\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            it(scenario.title, function(done) {\n                next(scenario, done);\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            it(scenario.title, function() {\n                next(scenario);\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.6.2.js",
    "content": "(function(e){if(\"function\"==typeof bootstrap)bootstrap(\"yadda_umd\",e);else if(\"object\"==typeof exports)module.exports=e();else if(\"function\"==typeof define&&define.amd)define(e);else if(\"undefined\"!=typeof ses){if(!ses.ok())return;ses.makeYaddaumd=e}else\"undefined\"!=typeof window?window.yaddaumd=e():global.yaddaumd=e()})(function(){var define,ses,bootstrap,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]'); \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":16,\"./parsers/index\":18,\"./plugins/index\":21}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":16}],16:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":14,\"./Pirate\":15}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/; \n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);    \n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");        \n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};        \n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],18:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":17}],19:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],20:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() { \n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) { \n                next(scenario, done) \n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() { \n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":17,\"fs\":22}],21:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":19,\"./MochaPlugin\":20}],22:[function(require,module,exports){\n// nothing to see here... no file methods for the browser\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.6.3.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]'); \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":19,\"./plugins/index\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/; \n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);    \n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");        \n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};        \n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":18}],20:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],21:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() { \n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) { \n                next(scenario, done) \n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() { \n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":18,\"fs\":23}],22:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":20,\"./MochaPlugin\":21}],23:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.6.4.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g')); \n    var _this = this;       \n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };    \n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]'); \n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {  \n        return term_pattern.test(definition);\n    };  \n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":19,\"./plugins/index\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/; \n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);    \n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");        \n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};        \n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":18}],20:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],21:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() { \n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) { \n                next(scenario, done) \n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() { \n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":18,\"fs\":23}],22:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":20,\"./MochaPlugin\":21}],23:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.6.5.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.6.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":19,\"./plugins/index\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n   \nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar TextParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/; \n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);    \n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");        \n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};        \n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = TextParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\nmodule.exports = {\n    TextParser: require('./TextParser')\n}\n},{\"./TextParser\":18}],20:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],21:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar TextParser = require('../parsers/TextParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new TextParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() { \n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {        \n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) { \n                next(scenario, done) \n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() { \n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/TextParser\":18,\"fs\":23}],22:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":20,\"./MochaPlugin\":21}],23:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.7.0.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.7.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":20,\"./plugins/index\":23}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n   \nvar Pirate = function(dictionary, library) {\n        \n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = localisation.prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut) ', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;     \n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar FeatureParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/;\n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};\n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],20:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":18,\"./StepParser\":19}],21:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],22:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new FeatureParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/FeatureParser\":18,\"fs\":24}],23:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":21,\"./MochaPlugin\":22}],24:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.7.1.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.7.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":20,\"./plugins/index\":23}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n\nvar Pirate = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar FeatureParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/;\n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};\n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],20:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":18,\"./StepParser\":19}],21:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],22:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new FeatureParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/FeatureParser\":18,\"fs\":24}],23:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":21,\"./MochaPlugin\":22}],24:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.7.2.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.7.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":17,\"./parsers/index\":20,\"./plugins/index\":23}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nvar English = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = English;\n},{\"../Array\":1,\"../Library\":8}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar localisation = require('../localisation')\nvar $ = require('../Array');\n\nvar Pirate = function(dictionary, library) {\n\n    var library = library ? library : new Library(dictionary);\n\n    library.given = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.when = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Ww]hilst|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    library.then = function(signatures, fn, ctx) {\n        return $(signatures).each(function(signature) {\n            var signature = prefix_signature('(?:[Tt]hence|[Dd]emand|[Aa]nd|[Bb]ut)\\\\s+', signature);\n            return library.define(signature, fn, ctx);\n        });\n    };\n\n    function prefix_signature(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix);\n    };\n\n    return library;\n};\n\nmodule.exports = Pirate;\n},{\"../Array\":1,\"../Library\":8,\"../localisation\":17}],17:[function(require,module,exports){\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n\n}\n},{\"./English\":15,\"./Pirate\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar FeatureParser = function() {\n\n    var FEATURE_REGEX = /^\\s*Feature:\\s*(.*)/i;\n    var SCENARIO_REGEX = /^\\s*Scenario:\\s*(.*)/i;\n    var STEP_REGEX = /^\\s*([^\\s].*)/;\n    var COMMENT_REGEX = /^\\s*#/;\n    var NON_BLANK_REGEX = /[^\\s]/;\n    var SIMPLE_ANNOTATION_REGEX = /^@([^=]*)$/;\n    var NVP_ANNOTATION_REGEX = /^@([^=]*)=(.*)$/;\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = COMMENT_REGEX.test(line)) return;\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};\n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],20:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":18,\"./StepParser\":19}],21:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],22:[function(require,module,exports){\nvar fs = require('fs');\nvar Yadda = require('../Yadda');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var parser = options.parser || new FeatureParser();\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations.Pending ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Yadda\":11,\"../parsers/FeatureParser\":18,\"fs\":24}],23:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":21,\"./MochaPlugin\":22}],24:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.8.0.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands definitions of terms\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {    \n    \n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;    \n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);        \n    }; \n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };  \n\n    this.interpret = function(step, scenario_context, next) {   \n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));            \n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();            \n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };   \n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.7.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":18,\"./parsers/index\":21,\"./plugins/index\":24}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)'\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(['given', 'when', 'then']).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":8}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+'\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate')\n}\n},{\"./English\":15,\"./Pirate\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n    console.log(language.localise('scenario'));\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var STEP_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var COMMENT_REGEX = new RegExp('^\\\\s*#', 'i');\n    var NON_BLANK_REGEX = new RegExp('[^\\\\s]', 'i');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$', 'i');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$', 'i');\n\n    var feature;\n\tvar annotations;\n\n    this.parse = function(text, next) {\n        feature = undefined; annotations = {};\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n\t\treturn $(text.split(/\\n/)).find_all(non_blanks);\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = true;\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations[match[1]] = match[2];\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = COMMENT_REGEX.test(line)) return;\n        if (match = STEP_REGEX.exec(line)) return add_step(match[1]);\n    };\n\n    var create_feature = function(title, annoations) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, annotations: annotations, scenarios: [] };\n        annotations = {};\n    };\n\n    var add_scenario = function(title) {\n        var scenario = {title: title, annotations: annotations, steps: []};\n        annotations = {};\n        if (!feature) create_feature();\n        feature.scenarios.push(scenario);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":15}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],21:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":19,\"./StepParser\":20}],22:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],23:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../localisation/English\":15,\"../parsers/FeatureParser\":19,\"fs\":25}],24:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":22,\"./MochaPlugin\":23}],25:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.8.1.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":18,\"./parsers/index\":21,\"./plugins/index\":24}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)'\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(['given', 'when', 'then']).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":8}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+'\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":15,\"./Language\":16,\"./Pirate\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":15}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],21:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":19,\"./StepParser\":20}],22:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],23:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n            _describe(feature.title[0] || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title[0], function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title[0], function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../localisation/English\":15,\"../parsers/FeatureParser\":19,\"fs\":25}],24:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":22,\"./MochaPlugin\":23}],25:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.8.2.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'        \n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {                \n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items]; \n        if (items.length == 0) return [];    \n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) { \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) { \n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };    \n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);            \n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }        \n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {        \n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];                \n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":12}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":7}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":10}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":12}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":12}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":9}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":10,\"./fn\":12}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":6,\"./fn\":12}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {    \n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),    \n    Context: require('./Context'),    \n    Library: require('./Library'),    \n    Dictionary: require('./Dictionary'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./Interpreter\":6,\"./Library\":8,\"./Yadda\":11,\"./localisation/index\":19,\"./parsers/index\":22,\"./plugins/index\":25}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)'\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":16}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(['given', 'when', 'then']).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":8}],17:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)'\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":16}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+'\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":16}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":15,\"./Language\":16,\"./Norwegian\":17,\"./Pirate\":18}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":15}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],22:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":20,\"./StepParser\":21}],23:[function(require,module,exports){\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });        \n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);            \n        });  \n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }    \n};\n},{\"yadda\":\"W+dgdo\"}],24:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filename, next) {\n        var text = fs.readFileSync(filename, 'utf8');\n        parser.parse(text, function(feature) {\n            var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n            _describe(feature.title || filename, function() {\n                next(feature)\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../localisation/English\":15,\"../parsers/FeatureParser\":20,\"fs\":26}],25:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":23,\"./MochaPlugin\":24}],26:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.8.3.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)'\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(['given', 'when', 'then']).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)'\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+'\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"W+dgdo\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":36,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":36,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\nvar Buffer=require(\"__browserify_Buffer\").Buffer;// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg instanceof Buffer;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"__browserify_Buffer\":35,\"_shims\":31}],35:[function(require,module,exports){\nrequire=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\nexports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {\n  var e, m,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      nBits = -7,\n      i = isBE ? 0 : (nBytes - 1),\n      d = isBE ? 1 : -1,\n      s = buffer[offset + i];\n\n  i += d;\n\n  e = s & ((1 << (-nBits)) - 1);\n  s >>= (-nBits);\n  nBits += eLen;\n  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  m = e & ((1 << (-nBits)) - 1);\n  e >>= (-nBits);\n  nBits += mLen;\n  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  if (e === 0) {\n    e = 1 - eBias;\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity);\n  } else {\n    m = m + Math.pow(2, mLen);\n    e = e - eBias;\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);\n};\n\nexports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {\n  var e, m, c,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),\n      i = isBE ? (nBytes - 1) : 0,\n      d = isBE ? -1 : 1,\n      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;\n\n  value = Math.abs(value);\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0;\n    e = eMax;\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2);\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--;\n      c *= 2;\n    }\n    if (e + eBias >= 1) {\n      value += rt / c;\n    } else {\n      value += rt * Math.pow(2, 1 - eBias);\n    }\n    if (value * c >= 2) {\n      e++;\n      c /= 2;\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0;\n      e = eMax;\n    } else if (e + eBias >= 1) {\n      m = (value * c - 1) * Math.pow(2, mLen);\n      e = e + eBias;\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);\n      e = 0;\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);\n\n  e = (e << mLen) | m;\n  eLen += mLen;\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);\n\n  buffer[offset + i - d] |= s * 128;\n};\n\n},{}],\"q9TxCC\":[function(require,module,exports){\nvar assert;\nexports.Buffer = Buffer;\nexports.SlowBuffer = Buffer;\nBuffer.poolSize = 8192;\nexports.INSPECT_MAX_BYTES = 50;\n\nfunction stringtrim(str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n}\n\nfunction Buffer(subject, encoding, offset) {\n  if(!assert) assert= require('assert');\n  if (!(this instanceof Buffer)) {\n    return new Buffer(subject, encoding, offset);\n  }\n  this.parent = this;\n  this.offset = 0;\n\n  // Work-around: node's base64 implementation\n  // allows for non-padded strings while base64-js\n  // does not..\n  if (encoding == \"base64\" && typeof subject == \"string\") {\n    subject = stringtrim(subject);\n    while (subject.length % 4 != 0) {\n      subject = subject + \"=\"; \n    }\n  }\n\n  var type;\n\n  // Are we slicing?\n  if (typeof offset === 'number') {\n    this.length = coerce(encoding);\n    // slicing works, with limitations (no parent tracking/update)\n    // check https://github.com/toots/buffer-browserify/issues/19\n    for (var i = 0; i < this.length; i++) {\n        this[i] = subject.get(i+offset);\n    }\n  } else {\n    // Find the length\n    switch (type = typeof subject) {\n      case 'number':\n        this.length = coerce(subject);\n        break;\n\n      case 'string':\n        this.length = Buffer.byteLength(subject, encoding);\n        break;\n\n      case 'object': // Assume object is an array\n        this.length = coerce(subject.length);\n        break;\n\n      default:\n        throw new Error('First argument needs to be a number, ' +\n                        'array or string.');\n    }\n\n    // Treat array-ish objects as a byte array.\n    if (isArrayIsh(subject)) {\n      for (var i = 0; i < this.length; i++) {\n        if (subject instanceof Buffer) {\n          this[i] = subject.readUInt8(i);\n        }\n        else {\n          this[i] = subject[i];\n        }\n      }\n    } else if (type == 'string') {\n      // We are a string\n      this.length = this.write(subject, 0, encoding);\n    } else if (type === 'number') {\n      for (var i = 0; i < this.length; i++) {\n        this[i] = 0;\n      }\n    }\n  }\n}\n\nBuffer.prototype.get = function get(i) {\n  if (i < 0 || i >= this.length) throw new Error('oob');\n  return this[i];\n};\n\nBuffer.prototype.set = function set(i, v) {\n  if (i < 0 || i >= this.length) throw new Error('oob');\n  return this[i] = v;\n};\n\nBuffer.byteLength = function (str, encoding) {\n  switch (encoding || \"utf8\") {\n    case 'hex':\n      return str.length / 2;\n\n    case 'utf8':\n    case 'utf-8':\n      return utf8ToBytes(str).length;\n\n    case 'ascii':\n    case 'binary':\n      return str.length;\n\n    case 'base64':\n      return base64ToBytes(str).length;\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\nBuffer.prototype.utf8Write = function (string, offset, length) {\n  var bytes, pos;\n  return Buffer._charsWritten =  blitBuffer(utf8ToBytes(string), this, offset, length);\n};\n\nBuffer.prototype.asciiWrite = function (string, offset, length) {\n  var bytes, pos;\n  return Buffer._charsWritten =  blitBuffer(asciiToBytes(string), this, offset, length);\n};\n\nBuffer.prototype.binaryWrite = Buffer.prototype.asciiWrite;\n\nBuffer.prototype.base64Write = function (string, offset, length) {\n  var bytes, pos;\n  return Buffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);\n};\n\nBuffer.prototype.base64Slice = function (start, end) {\n  var bytes = Array.prototype.slice.apply(this, arguments)\n  return require(\"base64-js\").fromByteArray(bytes);\n};\n\nBuffer.prototype.utf8Slice = function () {\n  var bytes = Array.prototype.slice.apply(this, arguments);\n  var res = \"\";\n  var tmp = \"\";\n  var i = 0;\n  while (i < bytes.length) {\n    if (bytes[i] <= 0x7F) {\n      res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);\n      tmp = \"\";\n    } else\n      tmp += \"%\" + bytes[i].toString(16);\n\n    i++;\n  }\n\n  return res + decodeUtf8Char(tmp);\n}\n\nBuffer.prototype.asciiSlice = function () {\n  var bytes = Array.prototype.slice.apply(this, arguments);\n  var ret = \"\";\n  for (var i = 0; i < bytes.length; i++)\n    ret += String.fromCharCode(bytes[i]);\n  return ret;\n}\n\nBuffer.prototype.binarySlice = Buffer.prototype.asciiSlice;\n\nBuffer.prototype.inspect = function() {\n  var out = [],\n      len = this.length;\n  for (var i = 0; i < len; i++) {\n    out[i] = toHex(this[i]);\n    if (i == exports.INSPECT_MAX_BYTES) {\n      out[i + 1] = '...';\n      break;\n    }\n  }\n  return '<Buffer ' + out.join(' ') + '>';\n};\n\n\nBuffer.prototype.hexSlice = function(start, end) {\n  var len = this.length;\n\n  if (!start || start < 0) start = 0;\n  if (!end || end < 0 || end > len) end = len;\n\n  var out = '';\n  for (var i = start; i < end; i++) {\n    out += toHex(this[i]);\n  }\n  return out;\n};\n\n\nBuffer.prototype.toString = function(encoding, start, end) {\n  encoding = String(encoding || 'utf8').toLowerCase();\n  start = +start || 0;\n  if (typeof end == 'undefined') end = this.length;\n\n  // Fastpath empty strings\n  if (+end == start) {\n    return '';\n  }\n\n  switch (encoding) {\n    case 'hex':\n      return this.hexSlice(start, end);\n\n    case 'utf8':\n    case 'utf-8':\n      return this.utf8Slice(start, end);\n\n    case 'ascii':\n      return this.asciiSlice(start, end);\n\n    case 'binary':\n      return this.binarySlice(start, end);\n\n    case 'base64':\n      return this.base64Slice(start, end);\n\n    case 'ucs2':\n    case 'ucs-2':\n      return this.ucs2Slice(start, end);\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\n\nBuffer.prototype.hexWrite = function(string, offset, length) {\n  offset = +offset || 0;\n  var remaining = this.length - offset;\n  if (!length) {\n    length = remaining;\n  } else {\n    length = +length;\n    if (length > remaining) {\n      length = remaining;\n    }\n  }\n\n  // must be an even number of digits\n  var strLen = string.length;\n  if (strLen % 2) {\n    throw new Error('Invalid hex string');\n  }\n  if (length > strLen / 2) {\n    length = strLen / 2;\n  }\n  for (var i = 0; i < length; i++) {\n    var byte = parseInt(string.substr(i * 2, 2), 16);\n    if (isNaN(byte)) throw new Error('Invalid hex string');\n    this[offset + i] = byte;\n  }\n  Buffer._charsWritten = i * 2;\n  return i;\n};\n\n\nBuffer.prototype.write = function(string, offset, length, encoding) {\n  // Support both (string, offset, length, encoding)\n  // and the legacy (string, encoding, offset, length)\n  if (isFinite(offset)) {\n    if (!isFinite(length)) {\n      encoding = length;\n      length = undefined;\n    }\n  } else {  // legacy\n    var swap = encoding;\n    encoding = offset;\n    offset = length;\n    length = swap;\n  }\n\n  offset = +offset || 0;\n  var remaining = this.length - offset;\n  if (!length) {\n    length = remaining;\n  } else {\n    length = +length;\n    if (length > remaining) {\n      length = remaining;\n    }\n  }\n  encoding = String(encoding || 'utf8').toLowerCase();\n\n  switch (encoding) {\n    case 'hex':\n      return this.hexWrite(string, offset, length);\n\n    case 'utf8':\n    case 'utf-8':\n      return this.utf8Write(string, offset, length);\n\n    case 'ascii':\n      return this.asciiWrite(string, offset, length);\n\n    case 'binary':\n      return this.binaryWrite(string, offset, length);\n\n    case 'base64':\n      return this.base64Write(string, offset, length);\n\n    case 'ucs2':\n    case 'ucs-2':\n      return this.ucs2Write(string, offset, length);\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\n// slice(start, end)\nfunction clamp(index, len, defaultValue) {\n  if (typeof index !== 'number') return defaultValue;\n  index = ~~index;  // Coerce to integer.\n  if (index >= len) return len;\n  if (index >= 0) return index;\n  index += len;\n  if (index >= 0) return index;\n  return 0;\n}\n\nBuffer.prototype.slice = function(start, end) {\n  var len = this.length;\n  start = clamp(start, len, 0);\n  end = clamp(end, len, len);\n  return new Buffer(this, end - start, +start);\n};\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function(target, target_start, start, end) {\n  var source = this;\n  start || (start = 0);\n  if (end === undefined || isNaN(end)) {\n    end = this.length;\n  }\n  target_start || (target_start = 0);\n\n  if (end < start) throw new Error('sourceEnd < sourceStart');\n\n  // Copy 0 bytes; we're done\n  if (end === start) return 0;\n  if (target.length == 0 || source.length == 0) return 0;\n\n  if (target_start < 0 || target_start >= target.length) {\n    throw new Error('targetStart out of bounds');\n  }\n\n  if (start < 0 || start >= source.length) {\n    throw new Error('sourceStart out of bounds');\n  }\n\n  if (end < 0 || end > source.length) {\n    throw new Error('sourceEnd out of bounds');\n  }\n\n  // Are we oob?\n  if (end > this.length) {\n    end = this.length;\n  }\n\n  if (target.length - target_start < end - start) {\n    end = target.length - target_start + start;\n  }\n\n  var temp = [];\n  for (var i=start; i<end; i++) {\n    assert.ok(typeof this[i] !== 'undefined', \"copying undefined buffer bytes!\");\n    temp.push(this[i]);\n  }\n\n  for (var i=target_start; i<target_start+temp.length; i++) {\n    target[i] = temp[i-target_start];\n  }\n};\n\n// fill(value, start=0, end=buffer.length)\nBuffer.prototype.fill = function fill(value, start, end) {\n  value || (value = 0);\n  start || (start = 0);\n  end || (end = this.length);\n\n  if (typeof value === 'string') {\n    value = value.charCodeAt(0);\n  }\n  if (!(typeof value === 'number') || isNaN(value)) {\n    throw new Error('value is not a number');\n  }\n\n  if (end < start) throw new Error('end < start');\n\n  // Fill 0 bytes; we're done\n  if (end === start) return 0;\n  if (this.length == 0) return 0;\n\n  if (start < 0 || start >= this.length) {\n    throw new Error('start out of bounds');\n  }\n\n  if (end < 0 || end > this.length) {\n    throw new Error('end out of bounds');\n  }\n\n  for (var i = start; i < end; i++) {\n    this[i] = value;\n  }\n}\n\n// Static methods\nBuffer.isBuffer = function isBuffer(b) {\n  return b instanceof Buffer || b instanceof Buffer;\n};\n\nBuffer.concat = function (list, totalLength) {\n  if (!isArray(list)) {\n    throw new Error(\"Usage: Buffer.concat(list, [totalLength])\\n \\\n      list should be an Array.\");\n  }\n\n  if (list.length === 0) {\n    return new Buffer(0);\n  } else if (list.length === 1) {\n    return list[0];\n  }\n\n  if (typeof totalLength !== 'number') {\n    totalLength = 0;\n    for (var i = 0; i < list.length; i++) {\n      var buf = list[i];\n      totalLength += buf.length;\n    }\n  }\n\n  var buffer = new Buffer(totalLength);\n  var pos = 0;\n  for (var i = 0; i < list.length; i++) {\n    var buf = list[i];\n    buf.copy(buffer, pos);\n    pos += buf.length;\n  }\n  return buffer;\n};\n\nBuffer.isEncoding = function(encoding) {\n  switch ((encoding + '').toLowerCase()) {\n    case 'hex':\n    case 'utf8':\n    case 'utf-8':\n    case 'ascii':\n    case 'binary':\n    case 'base64':\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n    case 'raw':\n      return true;\n\n    default:\n      return false;\n  }\n};\n\n// helpers\n\nfunction coerce(length) {\n  // Coerce length to a number (possibly NaN), round up\n  // in case it's fractional (e.g. 123.456) then do a\n  // double negate to coerce a NaN to 0. Easy, right?\n  length = ~~Math.ceil(+length);\n  return length < 0 ? 0 : length;\n}\n\nfunction isArray(subject) {\n  return (Array.isArray ||\n    function(subject){\n      return {}.toString.apply(subject) == '[object Array]'\n    })\n    (subject)\n}\n\nfunction isArrayIsh(subject) {\n  return isArray(subject) || Buffer.isBuffer(subject) ||\n         subject && typeof subject === 'object' &&\n         typeof subject.length === 'number';\n}\n\nfunction toHex(n) {\n  if (n < 16) return '0' + n.toString(16);\n  return n.toString(16);\n}\n\nfunction utf8ToBytes(str) {\n  var byteArray = [];\n  for (var i = 0; i < str.length; i++)\n    if (str.charCodeAt(i) <= 0x7F)\n      byteArray.push(str.charCodeAt(i));\n    else {\n      var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');\n      for (var j = 0; j < h.length; j++)\n        byteArray.push(parseInt(h[j], 16));\n    }\n\n  return byteArray;\n}\n\nfunction asciiToBytes(str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++ )\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push( str.charCodeAt(i) & 0xFF );\n\n  return byteArray;\n}\n\nfunction base64ToBytes(str) {\n  return require(\"base64-js\").toByteArray(str);\n}\n\nfunction blitBuffer(src, dst, offset, length) {\n  var pos, i = 0;\n  while (i < length) {\n    if ((i+offset >= dst.length) || (i >= src.length))\n      break;\n\n    dst[i + offset] = src[i];\n    i++;\n  }\n  return i;\n}\n\nfunction decodeUtf8Char(str) {\n  try {\n    return decodeURIComponent(str);\n  } catch (err) {\n    return String.fromCharCode(0xFFFD); // UTF 8 invalid char\n  }\n}\n\n// read/write bit-twiddling\n\nBuffer.prototype.readUInt8 = function(offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return;\n\n  return buffer[offset];\n};\n\nfunction readUInt16(buffer, offset, isBigEndian, noAssert) {\n  var val = 0;\n\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return 0;\n\n  if (isBigEndian) {\n    val = buffer[offset] << 8;\n    if (offset + 1 < buffer.length) {\n      val |= buffer[offset + 1];\n    }\n  } else {\n    val = buffer[offset];\n    if (offset + 1 < buffer.length) {\n      val |= buffer[offset + 1] << 8;\n    }\n  }\n\n  return val;\n}\n\nBuffer.prototype.readUInt16LE = function(offset, noAssert) {\n  return readUInt16(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readUInt16BE = function(offset, noAssert) {\n  return readUInt16(this, offset, true, noAssert);\n};\n\nfunction readUInt32(buffer, offset, isBigEndian, noAssert) {\n  var val = 0;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return 0;\n\n  if (isBigEndian) {\n    if (offset + 1 < buffer.length)\n      val = buffer[offset + 1] << 16;\n    if (offset + 2 < buffer.length)\n      val |= buffer[offset + 2] << 8;\n    if (offset + 3 < buffer.length)\n      val |= buffer[offset + 3];\n    val = val + (buffer[offset] << 24 >>> 0);\n  } else {\n    if (offset + 2 < buffer.length)\n      val = buffer[offset + 2] << 16;\n    if (offset + 1 < buffer.length)\n      val |= buffer[offset + 1] << 8;\n    val |= buffer[offset];\n    if (offset + 3 < buffer.length)\n      val = val + (buffer[offset + 3] << 24 >>> 0);\n  }\n\n  return val;\n}\n\nBuffer.prototype.readUInt32LE = function(offset, noAssert) {\n  return readUInt32(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readUInt32BE = function(offset, noAssert) {\n  return readUInt32(this, offset, true, noAssert);\n};\n\n\n/*\n * Signed integer types, yay team! A reminder on how two's complement actually\n * works. The first bit is the signed bit, i.e. tells us whether or not the\n * number should be positive or negative. If the two's complement value is\n * positive, then we're done, as it's equivalent to the unsigned representation.\n *\n * Now if the number is positive, you're pretty much done, you can just leverage\n * the unsigned translations and return those. Unfortunately, negative numbers\n * aren't quite that straightforward.\n *\n * At first glance, one might be inclined to use the traditional formula to\n * translate binary numbers between the positive and negative values in two's\n * complement. (Though it doesn't quite work for the most negative value)\n * Mainly:\n *  - invert all the bits\n *  - add one to the result\n *\n * Of course, this doesn't quite work in Javascript. Take for example the value\n * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of\n * course, Javascript will do the following:\n *\n * > ~0xff80\n * -65409\n *\n * Whoh there, Javascript, that's not quite right. But wait, according to\n * Javascript that's perfectly correct. When Javascript ends up seeing the\n * constant 0xff80, it has no notion that it is actually a signed number. It\n * assumes that we've input the unsigned value 0xff80. Thus, when it does the\n * binary negation, it casts it into a signed value, (positive 0xff80). Then\n * when you perform binary negation on that, it turns it into a negative number.\n *\n * Instead, we're going to have to use the following general formula, that works\n * in a rather Javascript friendly way. I'm glad we don't support this kind of\n * weird numbering scheme in the kernel.\n *\n * (BIT-MAX - (unsigned)val + 1) * -1\n *\n * The astute observer, may think that this doesn't make sense for 8-bit numbers\n * (really it isn't necessary for them). However, when you get 16-bit numbers,\n * you do. Let's go back to our prior example and see how this will look:\n *\n * (0xffff - 0xff80 + 1) * -1\n * (0x007f + 1) * -1\n * (0x0080) * -1\n */\nBuffer.prototype.readInt8 = function(offset, noAssert) {\n  var buffer = this;\n  var neg;\n\n  if (!noAssert) {\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return;\n\n  neg = buffer[offset] & 0x80;\n  if (!neg) {\n    return (buffer[offset]);\n  }\n\n  return ((0xff - buffer[offset] + 1) * -1);\n};\n\nfunction readInt16(buffer, offset, isBigEndian, noAssert) {\n  var neg, val;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  val = readUInt16(buffer, offset, isBigEndian, noAssert);\n  neg = val & 0x8000;\n  if (!neg) {\n    return val;\n  }\n\n  return (0xffff - val + 1) * -1;\n}\n\nBuffer.prototype.readInt16LE = function(offset, noAssert) {\n  return readInt16(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readInt16BE = function(offset, noAssert) {\n  return readInt16(this, offset, true, noAssert);\n};\n\nfunction readInt32(buffer, offset, isBigEndian, noAssert) {\n  var neg, val;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  val = readUInt32(buffer, offset, isBigEndian, noAssert);\n  neg = val & 0x80000000;\n  if (!neg) {\n    return (val);\n  }\n\n  return (0xffffffff - val + 1) * -1;\n}\n\nBuffer.prototype.readInt32LE = function(offset, noAssert) {\n  return readInt32(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readInt32BE = function(offset, noAssert) {\n  return readInt32(this, offset, true, noAssert);\n};\n\nfunction readFloat(buffer, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,\n      23, 4);\n}\n\nBuffer.prototype.readFloatLE = function(offset, noAssert) {\n  return readFloat(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readFloatBE = function(offset, noAssert) {\n  return readFloat(this, offset, true, noAssert);\n};\n\nfunction readDouble(buffer, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset + 7 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,\n      52, 8);\n}\n\nBuffer.prototype.readDoubleLE = function(offset, noAssert) {\n  return readDouble(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readDoubleBE = function(offset, noAssert) {\n  return readDouble(this, offset, true, noAssert);\n};\n\n\n/*\n * We have to make sure that the value is a valid integer. This means that it is\n * non-negative. It has no fractional component and that it does not exceed the\n * maximum allowed value.\n *\n *      value           The number to check for validity\n *\n *      max             The maximum value\n */\nfunction verifuint(value, max) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value >= 0,\n      'specified a negative value for writing an unsigned value');\n\n  assert.ok(value <= max, 'value is larger than maximum value for type');\n\n  assert.ok(Math.floor(value) === value, 'value has a fractional component');\n}\n\nBuffer.prototype.writeUInt8 = function(value, offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xff);\n  }\n\n  if (offset < buffer.length) {\n    buffer[offset] = value;\n  }\n};\n\nfunction writeUInt16(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xffff);\n  }\n\n  for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {\n    buffer[offset + i] =\n        (value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>\n            (isBigEndian ? 1 - i : i) * 8;\n  }\n\n}\n\nBuffer.prototype.writeUInt16LE = function(value, offset, noAssert) {\n  writeUInt16(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeUInt16BE = function(value, offset, noAssert) {\n  writeUInt16(this, value, offset, true, noAssert);\n};\n\nfunction writeUInt32(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xffffffff);\n  }\n\n  for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {\n    buffer[offset + i] =\n        (value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;\n  }\n}\n\nBuffer.prototype.writeUInt32LE = function(value, offset, noAssert) {\n  writeUInt32(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeUInt32BE = function(value, offset, noAssert) {\n  writeUInt32(this, value, offset, true, noAssert);\n};\n\n\n/*\n * We now move onto our friends in the signed number category. Unlike unsigned\n * numbers, we're going to have to worry a bit more about how we put values into\n * arrays. Since we are only worrying about signed 32-bit values, we're in\n * slightly better shape. Unfortunately, we really can't do our favorite binary\n * & in this system. It really seems to do the wrong thing. For example:\n *\n * > -32 & 0xff\n * 224\n *\n * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of\n * this aren't treated as a signed number. Ultimately a bad thing.\n *\n * What we're going to want to do is basically create the unsigned equivalent of\n * our representation and pass that off to the wuint* functions. To do that\n * we're going to do the following:\n *\n *  - if the value is positive\n *      we can pass it directly off to the equivalent wuint\n *  - if the value is negative\n *      we do the following computation:\n *         mb + val + 1, where\n *         mb   is the maximum unsigned value in that byte size\n *         val  is the Javascript negative integer\n *\n *\n * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If\n * you do out the computations:\n *\n * 0xffff - 128 + 1\n * 0xffff - 127\n * 0xff80\n *\n * You can then encode this value as the signed version. This is really rather\n * hacky, but it should work and get the job done which is our goal here.\n */\n\n/*\n * A series of checks to make sure we actually have a signed 32-bit number\n */\nfunction verifsint(value, max, min) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value <= max, 'value larger than maximum allowed value');\n\n  assert.ok(value >= min, 'value smaller than minimum allowed value');\n\n  assert.ok(Math.floor(value) === value, 'value has a fractional component');\n}\n\nfunction verifIEEE754(value, max, min) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value <= max, 'value larger than maximum allowed value');\n\n  assert.ok(value >= min, 'value smaller than minimum allowed value');\n}\n\nBuffer.prototype.writeInt8 = function(value, offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7f, -0x80);\n  }\n\n  if (value >= 0) {\n    buffer.writeUInt8(value, offset, noAssert);\n  } else {\n    buffer.writeUInt8(0xff + value + 1, offset, noAssert);\n  }\n};\n\nfunction writeInt16(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7fff, -0x8000);\n  }\n\n  if (value >= 0) {\n    writeUInt16(buffer, value, offset, isBigEndian, noAssert);\n  } else {\n    writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);\n  }\n}\n\nBuffer.prototype.writeInt16LE = function(value, offset, noAssert) {\n  writeInt16(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeInt16BE = function(value, offset, noAssert) {\n  writeInt16(this, value, offset, true, noAssert);\n};\n\nfunction writeInt32(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7fffffff, -0x80000000);\n  }\n\n  if (value >= 0) {\n    writeUInt32(buffer, value, offset, isBigEndian, noAssert);\n  } else {\n    writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);\n  }\n}\n\nBuffer.prototype.writeInt32LE = function(value, offset, noAssert) {\n  writeInt32(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeInt32BE = function(value, offset, noAssert) {\n  writeInt32(this, value, offset, true, noAssert);\n};\n\nfunction writeFloat(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);\n  }\n\n  require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,\n      23, 4);\n}\n\nBuffer.prototype.writeFloatLE = function(value, offset, noAssert) {\n  writeFloat(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeFloatBE = function(value, offset, noAssert) {\n  writeFloat(this, value, offset, true, noAssert);\n};\n\nfunction writeDouble(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 7 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);\n  }\n\n  require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,\n      52, 8);\n}\n\nBuffer.prototype.writeDoubleLE = function(value, offset, noAssert) {\n  writeDouble(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeDoubleBE = function(value, offset, noAssert) {\n  writeDouble(this, value, offset, true, noAssert);\n};\n\n},{\"./buffer_ieee754\":1,\"assert\":6,\"base64-js\":4}],\"buffer-browserify\":[function(require,module,exports){\nmodule.exports=require('q9TxCC');\n},{}],4:[function(require,module,exports){\n(function (exports) {\n\t'use strict';\n\n\tvar lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n\tfunction b64ToByteArray(b64) {\n\t\tvar i, j, l, tmp, placeHolders, arr;\n\t\n\t\tif (b64.length % 4 > 0) {\n\t\t\tthrow 'Invalid string. Length must be a multiple of 4';\n\t\t}\n\n\t\t// the number of equal signs (place holders)\n\t\t// if there are two placeholders, than the two characters before it\n\t\t// represent one byte\n\t\t// if there is only one, then the three characters before it represent 2 bytes\n\t\t// this is just a cheap hack to not do indexOf twice\n\t\tplaceHolders = b64.indexOf('=');\n\t\tplaceHolders = placeHolders > 0 ? b64.length - placeHolders : 0;\n\n\t\t// base64 is 4/3 + up to two characters of the original data\n\t\tarr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);\n\n\t\t// if there are placeholders, only get up to the last complete 4 chars\n\t\tl = placeHolders > 0 ? b64.length - 4 : b64.length;\n\n\t\tfor (i = 0, j = 0; i < l; i += 4, j += 3) {\n\t\t\ttmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);\n\t\t\tarr.push((tmp & 0xFF0000) >> 16);\n\t\t\tarr.push((tmp & 0xFF00) >> 8);\n\t\t\tarr.push(tmp & 0xFF);\n\t\t}\n\n\t\tif (placeHolders === 2) {\n\t\t\ttmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);\n\t\t\tarr.push(tmp & 0xFF);\n\t\t} else if (placeHolders === 1) {\n\t\t\ttmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);\n\t\t\tarr.push((tmp >> 8) & 0xFF);\n\t\t\tarr.push(tmp & 0xFF);\n\t\t}\n\n\t\treturn arr;\n\t}\n\n\tfunction uint8ToBase64(uint8) {\n\t\tvar i,\n\t\t\textraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes\n\t\t\toutput = \"\",\n\t\t\ttemp, length;\n\n\t\tfunction tripletToBase64 (num) {\n\t\t\treturn lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];\n\t\t};\n\n\t\t// go through the array every three bytes, we'll deal with trailing stuff later\n\t\tfor (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {\n\t\t\ttemp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);\n\t\t\toutput += tripletToBase64(temp);\n\t\t}\n\n\t\t// pad the end with zeros, but make sure to not forget the extra bytes\n\t\tswitch (extraBytes) {\n\t\t\tcase 1:\n\t\t\t\ttemp = uint8[uint8.length - 1];\n\t\t\t\toutput += lookup[temp >> 2];\n\t\t\t\toutput += lookup[(temp << 4) & 0x3F];\n\t\t\t\toutput += '==';\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\ttemp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);\n\t\t\t\toutput += lookup[temp >> 10];\n\t\t\t\toutput += lookup[(temp >> 4) & 0x3F];\n\t\t\t\toutput += lookup[(temp << 2) & 0x3F];\n\t\t\t\toutput += '=';\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn output;\n\t}\n\n\tmodule.exports.toByteArray = b64ToByteArray;\n\tmodule.exports.fromByteArray = uint8ToBase64;\n}());\n\n},{}],5:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],6:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// UTILITY\nvar util = require('util');\nvar shims = require('_shims');\nvar pSlice = Array.prototype.slice;\n\n// 1. The assert module provides functions that throw\n// AssertionError's when particular conditions are not met. The\n// assert module must conform to the following interface.\n\nvar assert = module.exports = ok;\n\n// 2. The AssertionError is defined in assert.\n// new assert.AssertionError({ message: message,\n//                             actual: actual,\n//                             expected: expected })\n\nassert.AssertionError = function AssertionError(options) {\n  this.name = 'AssertionError';\n  this.actual = options.actual;\n  this.expected = options.expected;\n  this.operator = options.operator;\n  this.message = options.message || getMessage(this);\n};\n\n// assert.AssertionError instanceof Error\nutil.inherits(assert.AssertionError, Error);\n\nfunction replacer(key, value) {\n  if (util.isUndefined(value)) {\n    return '' + value;\n  }\n  if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {\n    return value.toString();\n  }\n  if (util.isFunction(value) || util.isRegExp(value)) {\n    return value.toString();\n  }\n  return value;\n}\n\nfunction truncate(s, n) {\n  if (util.isString(s)) {\n    return s.length < n ? s : s.slice(0, n);\n  } else {\n    return s;\n  }\n}\n\nfunction getMessage(self) {\n  return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +\n         self.operator + ' ' +\n         truncate(JSON.stringify(self.expected, replacer), 128);\n}\n\n// At present only the three keys mentioned above are used and\n// understood by the spec. Implementations or sub modules can pass\n// other keys to the AssertionError's constructor - they will be\n// ignored.\n\n// 3. All of the following functions must throw an AssertionError\n// when a corresponding condition is not met, with a message that\n// may be undefined if not provided.  All assertion methods provide\n// both the actual and expected values to the assertion error for\n// display purposes.\n\nfunction fail(actual, expected, message, operator, stackStartFunction) {\n  throw new assert.AssertionError({\n    message: message,\n    actual: actual,\n    expected: expected,\n    operator: operator,\n    stackStartFunction: stackStartFunction\n  });\n}\n\n// EXTENSION! allows for well behaved errors defined elsewhere.\nassert.fail = fail;\n\n// 4. Pure assertion tests whether a value is truthy, as determined\n// by !!guard.\n// assert.ok(guard, message_opt);\n// This statement is equivalent to assert.equal(true, !!guard,\n// message_opt);. To test strictly for the value true, use\n// assert.strictEqual(true, guard, message_opt);.\n\nfunction ok(value, message) {\n  if (!value) fail(value, true, message, '==', assert.ok);\n}\nassert.ok = ok;\n\n// 5. The equality assertion tests shallow, coercive equality with\n// ==.\n// assert.equal(actual, expected, message_opt);\n\nassert.equal = function equal(actual, expected, message) {\n  if (actual != expected) fail(actual, expected, message, '==', assert.equal);\n};\n\n// 6. The non-equality assertion tests for whether two objects are not equal\n// with != assert.notEqual(actual, expected, message_opt);\n\nassert.notEqual = function notEqual(actual, expected, message) {\n  if (actual == expected) {\n    fail(actual, expected, message, '!=', assert.notEqual);\n  }\n};\n\n// 7. The equivalence assertion tests a deep equality relation.\n// assert.deepEqual(actual, expected, message_opt);\n\nassert.deepEqual = function deepEqual(actual, expected, message) {\n  if (!_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'deepEqual', assert.deepEqual);\n  }\n};\n\nfunction _deepEqual(actual, expected) {\n  // 7.1. All identical values are equivalent, as determined by ===.\n  if (actual === expected) {\n    return true;\n\n  } else if (util.isBuffer(actual) && util.isBuffer(expected)) {\n    if (actual.length != expected.length) return false;\n\n    for (var i = 0; i < actual.length; i++) {\n      if (actual[i] !== expected[i]) return false;\n    }\n\n    return true;\n\n  // 7.2. If the expected value is a Date object, the actual value is\n  // equivalent if it is also a Date object that refers to the same time.\n  } else if (util.isDate(actual) && util.isDate(expected)) {\n    return actual.getTime() === expected.getTime();\n\n  // 7.3 If the expected value is a RegExp object, the actual value is\n  // equivalent if it is also a RegExp object with the same source and\n  // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).\n  } else if (util.isRegExp(actual) && util.isRegExp(expected)) {\n    return actual.source === expected.source &&\n           actual.global === expected.global &&\n           actual.multiline === expected.multiline &&\n           actual.lastIndex === expected.lastIndex &&\n           actual.ignoreCase === expected.ignoreCase;\n\n  // 7.4. Other pairs that do not both pass typeof value == 'object',\n  // equivalence is determined by ==.\n  } else if (!util.isObject(actual) && !util.isObject(expected)) {\n    return actual == expected;\n\n  // 7.5 For all other Object pairs, including Array objects, equivalence is\n  // determined by having the same number of owned properties (as verified\n  // with Object.prototype.hasOwnProperty.call), the same set of keys\n  // (although not necessarily the same order), equivalent values for every\n  // corresponding key, and an identical 'prototype' property. Note: this\n  // accounts for both named and indexed properties on Arrays.\n  } else {\n    return objEquiv(actual, expected);\n  }\n}\n\nfunction isArguments(object) {\n  return Object.prototype.toString.call(object) == '[object Arguments]';\n}\n\nfunction objEquiv(a, b) {\n  if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))\n    return false;\n  // an identical 'prototype' property.\n  if (a.prototype !== b.prototype) return false;\n  //~~~I've managed to break Object.keys through screwy arguments passing.\n  //   Converting to array solves the problem.\n  if (isArguments(a)) {\n    if (!isArguments(b)) {\n      return false;\n    }\n    a = pSlice.call(a);\n    b = pSlice.call(b);\n    return _deepEqual(a, b);\n  }\n  try {\n    var ka = shims.keys(a),\n        kb = shims.keys(b),\n        key, i;\n  } catch (e) {//happens when one is a string literal and the other isn't\n    return false;\n  }\n  // having the same number of owned properties (keys incorporates\n  // hasOwnProperty)\n  if (ka.length != kb.length)\n    return false;\n  //the same set of keys (although not necessarily the same order),\n  ka.sort();\n  kb.sort();\n  //~~~cheap key test\n  for (i = ka.length - 1; i >= 0; i--) {\n    if (ka[i] != kb[i])\n      return false;\n  }\n  //equivalent values for every corresponding key, and\n  //~~~possibly expensive deep test\n  for (i = ka.length - 1; i >= 0; i--) {\n    key = ka[i];\n    if (!_deepEqual(a[key], b[key])) return false;\n  }\n  return true;\n}\n\n// 8. The non-equivalence assertion tests for any deep inequality.\n// assert.notDeepEqual(actual, expected, message_opt);\n\nassert.notDeepEqual = function notDeepEqual(actual, expected, message) {\n  if (_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);\n  }\n};\n\n// 9. The strict equality assertion tests strict equality, as determined by ===.\n// assert.strictEqual(actual, expected, message_opt);\n\nassert.strictEqual = function strictEqual(actual, expected, message) {\n  if (actual !== expected) {\n    fail(actual, expected, message, '===', assert.strictEqual);\n  }\n};\n\n// 10. The strict non-equality assertion tests for strict inequality, as\n// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);\n\nassert.notStrictEqual = function notStrictEqual(actual, expected, message) {\n  if (actual === expected) {\n    fail(actual, expected, message, '!==', assert.notStrictEqual);\n  }\n};\n\nfunction expectedException(actual, expected) {\n  if (!actual || !expected) {\n    return false;\n  }\n\n  if (Object.prototype.toString.call(expected) == '[object RegExp]') {\n    return expected.test(actual);\n  } else if (actual instanceof expected) {\n    return true;\n  } else if (expected.call({}, actual) === true) {\n    return true;\n  }\n\n  return false;\n}\n\nfunction _throws(shouldThrow, block, expected, message) {\n  var actual;\n\n  if (util.isString(expected)) {\n    message = expected;\n    expected = null;\n  }\n\n  try {\n    block();\n  } catch (e) {\n    actual = e;\n  }\n\n  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +\n            (message ? ' ' + message : '.');\n\n  if (shouldThrow && !actual) {\n    fail(actual, expected, 'Missing expected exception' + message);\n  }\n\n  if (!shouldThrow && expectedException(actual, expected)) {\n    fail(actual, expected, 'Got unwanted exception' + message);\n  }\n\n  if ((shouldThrow && actual && expected &&\n      !expectedException(actual, expected)) || (!shouldThrow && actual)) {\n    throw actual;\n  }\n}\n\n// 11. Expected to throw an error:\n// assert.throws(block, Error_opt, message_opt);\n\nassert.throws = function(block, /*optional*/error, /*optional*/message) {\n  _throws.apply(this, [true].concat(pSlice.call(arguments)));\n};\n\n// EXTENSION! This is annoying to write outside this module.\nassert.doesNotThrow = function(block, /*optional*/message) {\n  _throws.apply(this, [false].concat(pSlice.call(arguments)));\n};\n\nassert.ifError = function(err) { if (err) {throw err;}};\n},{\"_shims\":5,\"util\":7}],7:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg instanceof Buffer;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":5}]},{},[])\n;;module.exports=require(\"buffer-browserify\")\n\n},{}],36:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.8.4.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;\nreturn (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('W+dgdo');\n},{}],\"W+dgdo\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så']\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale)',\n        scenario: '(?:[Aa]dventure)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+',\n        when: '(?:[Ww]hilst|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+',\n        _steps: ['giveth', 'whilst', 'thence']\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"W+dgdo\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":35,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":35,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":31}],35:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"W+dgdo\"])\n(W+dgdo)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.8.5.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"3V0FPO\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":35,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":35,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":31}],35:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.8.6.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.8.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ee]genskap)',\n        scenario: '(?:[Ss]cenario)',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var feature;\n\tvar annotations;\n    var blocks;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(feature) || feature;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var reset = function() {\n        feature = undefined;\n        annotations = new Annotations();\n        blocks = new Blocks();\n    };\n\n    var parse_line = function(line) {\n        var match;\n        if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1]);\n\t\tif (match = NVP_ANNOTATION_REGEX.exec(line)) return annotations.add(match[1], match[2]);\n\t\tif (match = FEATURE_REGEX.exec(line)) return create_feature(match[1]);\n        if (match = SCENARIO_REGEX.exec(line)) return add_scenario(match[1]);\n        if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return toggle_comment();\n        if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n        if (match = BLANK_REGEX.test(line)) return blocks.end();\n        if (match = TEXT_REGEX.exec(line)) return add_text(match[1]);\n    };\n\n    var create_feature = function(title) {\n        if (feature) throw new Error(\"You can only specify a single feature\");\n        feature = { title: title, description: [], annotations: annotations.end(), scenarios: [] };\n        blocks.start('feature_description', undefined, write_feature_description);\n        return feature;\n    };\n\n    var ensure_feature = function() {\n        return feature || create_feature();\n    }\n\n    var add_scenario = function(title) {\n        var scenario = { title: title, annotations: annotations.end(), steps: [] };\n        ensure_feature().scenarios.push(scenario);\n    };\n\n    var toggle_comment = function() {\n        blocks.start('comment');\n    };\n\n    var add_text = function(text) {\n        if (blocks.open()) return blocks.write(text);\n        add_step(text);\n    };\n\n    var add_step = function(step) {\n        if (!feature || feature.scenarios.length == 0) throw new Error(\"Missing scenario\");\n        feature.scenarios.slice(-1)[0].steps.push(step);\n    };\n\n    var write_feature_description = function(lines) {\n        feature.description = feature.description.concat(lines);\n    };\n\n    var write_scenario_title = function(lines) {\n        feature.scenarios[feature.scenarios.length - 1].title = lines;\n    };\n};\n\nvar Annotations = function() {\n\n    var annotations = {};\n\n    this.add = function(key, value) {\n        annotations[key] = value || true;\n    };\n\n    this.end = function() {\n        var result = annotations;\n        annotations = {};\n        return result;\n    };\n};\n\nvar Blocks = function() {\n\n    var stack = [];\n    var block;\n\n    this.start = function(type, line, callback) {\n        if (this.open()) this.end();\n        block = new Block(type, callback).write(line);\n    };\n\n    this.toggle = function(type, line, callback) {\n        if (this.open(type)) return this.write(line).end();\n        this.start(type, line, callback);\n    };\n\n    this.open = function(type) {\n        return type ? block.is(type) : !!block;\n    };\n\n    this.write = function(line) {\n        line && block.write(line);\n        return this;\n    };\n\n    this.end = function() {\n        this.open() && block.end();\n        block = stack.pop();\n    };\n};\n\nvar Block = function(type, callback) {\n\n    var lines = [];\n\n    this.write = function(line) {\n        if (line) lines.push(line);\n        return this;\n    };\n\n    this.is = function(_type) {\n        return type == _type;\n    };\n\n    this.end = function() {\n        callback && callback(lines);\n    };\n}\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"3V0FPO\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations.Pending ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":35,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":35,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":31}],35:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.0.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":27}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.0 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":20,\"./parsers/index\":23,\"./plugins/index\":26,\"./shims/index\":27}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":17}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],18:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":17}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":17}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./Language\":17,\"./Norwegian\":18,\"./Pirate\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":13,\"../localisation/English\":16}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],23:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":21,\"./StepParser\":22}],24:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":32,\"yadda\":\"3V0FPO\"}],25:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":21,\"fs\":32}],26:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":24,\"./MochaPlugin\":25}],27:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":28,\"./phantom-path\":29,\"./phantom-process\":30,\"__browserify_process\":35,\"fs\":32,\"path\":33}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":32}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":32,\"path\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":32}],31:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],32:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],33:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":35,\"_shims\":31,\"util\":34}],34:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":31}],35:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.1.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":28}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.1 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":21,\"./parsers/index\":24,\"./plugins/index\":27,\"./shims/index\":28}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":18}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":18}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],19:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":18}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":18}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./French\":17,\"./Language\":18,\"./Norwegian\":19,\"./Pirate\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":13,\"../localisation/English\":16}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],24:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":22,\"./StepParser\":23}],25:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":33,\"yadda\":\"3V0FPO\"}],26:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":22,\"fs\":33}],27:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":25,\"./MochaPlugin\":26}],28:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":29,\"./phantom-path\":30,\"./phantom-process\":31,\"__browserify_process\":36,\"fs\":33,\"path\":34}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":33,\"path\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":33}],32:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],33:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],34:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":36,\"_shims\":32,\"util\":35}],35:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":32}],36:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.10.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.10 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.11.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.11 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.2.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":28}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.2 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":21,\"./parsers/index\":24,\"./plugins/index\":27,\"./shims/index\":28}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":18}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":18}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],19:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":18}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":18}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./French\":17,\"./Language\":18,\"./Norwegian\":19,\"./Pirate\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":13,\"../localisation/English\":16}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],24:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":22,\"./StepParser\":23}],25:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":33,\"yadda\":\"3V0FPO\"}],26:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":22,\"fs\":33}],27:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":25,\"./MochaPlugin\":26}],28:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":29,\"./phantom-path\":30,\"./phantom-process\":31,\"__browserify_process\":36,\"fs\":33,\"path\":34}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":33,\"path\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":33}],32:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],33:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],34:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":36,\"_shims\":32,\"util\":35}],35:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":32}],36:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.3.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":13}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];\n    var by_ascending_score = function(a, b) { return b.score.beats(a.score); };\n    var FIRST_PLACE = 0;\n    var SECOND_PLACE = 1;\n\n    this.clear_winner = function() {\n        if (number_of_competitors() == 0) throw new Error('Undefined Step: [' + step + ']');\n        if (joint_first_place()) throw new Error('Ambiguous Step: [' + step + ']');\n        return this.winner();\n    };   \n\n    var number_of_competitors = function() {\n        return results.length;\n    };\n\n    var joint_first_place = function() {\n        return (number_of_competitors() > 1) && \n            results[FIRST_PLACE].score.equals(results[SECOND_PLACE].score); \n    };\n\n    this.winner = function() {\n        return results[FIRST_PLACE].macro;\n    };\n\n    var rank = function(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":8}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":11}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":13}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":28}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });        \n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        _this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":13}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":11,\"./fn\":13}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.3 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":7,\"./fn\":13}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FileSearch\":6,\"./Interpreter\":7,\"./Library\":9,\"./Yadda\":12,\"./localisation/index\":21,\"./parsers/index\":24,\"./plugins/index\":27,\"./shims/index\":28}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":18}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":18}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":9}],19:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":18}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":18}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":16,\"./French\":17,\"./Language\":18,\"./Norwegian\":19,\"./Pirate\":20}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase()] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":13,\"../localisation/English\":16}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],24:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":22,\"./StepParser\":23}],25:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":33,\"yadda\":\"3V0FPO\"}],26:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":16,\"../parsers/FeatureParser\":22,\"fs\":33}],27:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":25,\"./MochaPlugin\":26}],28:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":29,\"./phantom-path\":30,\"./phantom-process\":31,\"__browserify_process\":36,\"fs\":33,\"path\":34}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":33}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":33,\"path\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":33}],32:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],33:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],34:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":36,\"_shims\":32,\"util\":35}],35:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":32}],36:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.4.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":29}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.4 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":22,\"./parsers/index\":25,\"./plugins/index\":28,\"./shims/index\":29}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n},{\"./Language\":19}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],25:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":23,\"./StepParser\":24}],26:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":34,\"yadda\":\"3V0FPO\"}],27:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        scenarios.forEach(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":23,\"fs\":34}],28:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":26,\"./MochaPlugin\":27}],29:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":30,\"./phantom-path\":31,\"./phantom-process\":32,\"__browserify_process\":37,\"fs\":34,\"path\":35}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":34,\"path\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":34}],33:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],34:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],35:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":37,\"_shims\":33,\"util\":36}],36:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":33}],37:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.5.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":29}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.5 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":22,\"./parsers/index\":25,\"./plugins/index\":28,\"./shims/index\":29}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'<|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],25:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":23,\"./StepParser\":24}],26:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":34,\"yadda\":\"3V0FPO\"}],27:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":23,\"fs\":34}],28:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":26,\"./MochaPlugin\":27}],29:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":30,\"./phantom-path\":31,\"./phantom-process\":32,\"__browserify_process\":37,\"fs\":34,\"path\":35}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":34,\"path\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":34}],33:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],34:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],35:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":37,\"_shims\":33,\"util\":36}],36:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":33}],37:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.6.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":29}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.6 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":22,\"./parsers/index\":25,\"./plugins/index\":28,\"./shims/index\":29}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],25:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":23,\"./StepParser\":24}],26:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":34,\"yadda\":\"3V0FPO\"}],27:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":23,\"fs\":34}],28:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":26,\"./MochaPlugin\":27}],29:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":30,\"./phantom-path\":31,\"./phantom-process\":32,\"__browserify_process\":37,\"fs\":34,\"path\":35}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":34}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":34,\"path\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":34}],33:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],34:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],35:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":37,\"_shims\":33,\"util\":36}],36:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":33}],37:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.7.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.7 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};var fs = require('fs');\n\nglobal.process = global.process || {\n    cwd: function() {\n        return fs.workingDirectory\n    }\n};\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nvar fs = require('fs');\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\n    function feature(filenames, next) {\n        $(filenames).each(function(filename) {\n            var text = fs.readFileSync(filename, 'utf8');\n            parser.parse(text, function(feature) {\n                var _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n                _describe(feature.title || filename, function() {\n                    next(feature)\n                });\n            });\n        });\n    };\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n    GLOBAL.features = GLOBAL.feature = feature;\n    GLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n};\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.8.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.8 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-0.9.9.js",
    "content": "!function(e){\"object\"==typeof exports?module.exports=e():\"function\"==typeof define&&define.amd?define(e):\"undefined\"!=typeof window?window.yaddaumd=e():\"undefined\"!=typeof global?global.yaddaumd=e():\"undefined\"!=typeof self&&(self.yaddaumd=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    };\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]'\n    };\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    };\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length == 0) return [];\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    };\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        };\n        return result;\n    };\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var completed = 0;\n        var iterate = function() {\n            iterator(items[completed], completed, function(err, result) {\n                if (err) return callback(err);\n                if (++completed >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    };\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i]));\n        }\n        return results;\n    };\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    };\n\n    function push_all(items, more_items) {\n        var more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n    };\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                results.push(items[i]);\n            }\n        };\n        return results;\n    };\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i])) {\n                result = items[i];\n                break;\n            }\n        };\n        return result;\n    };\n\n    function naked(items) {\n        return [].concat(items);\n    };\n\n    return ensure_array(obj);\n};\n},{\"./fn\":14}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar LevenshteinDistanceScore = require('./LevenshteinDistanceScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros) {\n\n    var results = [];   \n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };   \n\n    function is_undefined() {\n        return results.length == 0;\n    };\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score); \n    };\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    };\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return { \n                macro: macro, \n                score: new LevenshteinDistanceScore(step, macro.levenshtein_signature())\n            }\n        }).sort( by_ascending_score );\n    };\n\n    function by_ascending_score(a, b) { \n        return b.score.beats(a.score);\n    };\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    };\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    };\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n},{\"./Array\":1,\"./LevenshteinDistanceScore\":9}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other instanceof Context) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key] }; \n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    var prefix = prefix || '$';\n    var terms = {};\n    var term_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var _this = this;\n\n    this.define = function(term, definition) {\n        if (this.is_defined(term)) throw new Error('Duplicate definition: [' + term + ']');\n        terms[term] = normalise(definition);\n        return this;\n    };\n\n    this.is_defined = function(term) {\n        return terms[term];\n    };\n\n    this.expand = function(term, already_expanding) {\n        if (!is_expandable(term)) return term;\n        return expand_sub_terms(term, $(already_expanding));\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each_term(this.define.bind(this));\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each_term = function(callback) {\n        for (key in terms) {\n            callback(key, terms[key])\n        };\n    };\n\n    var expand_sub_terms = function(term, already_expanding) {\n        return get_sub_terms(term).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: \\[' + already_expanding.join(', ') + '\\]');\n            var sub_term_definition = expand_sub_term(sub_term, already_expanding);\n            return term = term.replace(prefix + sub_term, sub_term_definition);\n        });\n    };\n\n    var get_sub_terms = function(term) {\n        return term_pattern.groups(term);\n    }\n\n    var expand_sub_term = function(sub_term, already_expanding) {\n        var definition = terms[sub_term] || '(.+)';\n        return is_expandable(definition) ? _this.expand(definition, already_expanding.concat(sub_term)) : definition;\n    }\n\n    var normalise = function(definition) {\n        return definition.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    var is_expandable = function(definition) {\n        return term_pattern.test(definition);\n    };\n};\n\n\nmodule.exports = Dictionary;\n},{\"./Array\":1,\"./RegularExpression\":12}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);      \n        notify_handlers(event_name, event_data);\n        next && next();        \n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };  \n};\n\nfunction instance() {\n    return event_bus;\n};\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__'\n};\n},{\"./Array\":1,\"./fn\":14}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    }\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename)\n        })\n    };\n};\n\nmodule.exports = FileSearch;\n},{\"./Array\":1,\"./shims/index\":30}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            return _this.rank_macros(step).validate();\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;  \n    };\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    };\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);        \n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });        \n        this.rank_macros(step).clear_winner().interpret(step, context || {}, next);\n    };  \n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step));\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":14}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';    \n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion)\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.beats = function(other) {\n        return this.value < other.value;\n    } \n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type == other.type && this.value == other.value);\n    }   \n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n},{}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;    \n\n    this.define = function(signatures, fn, macro_context) {\n        $(signatures).each(function(signature) {            \n            define_macro(signature, fn, macro_context);\n        });\n        return this;        \n    };\n\n    var define_macro = function(signature, fn, macro_context) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context));\n    }\n\n    this.get_macro = function(signature) {      \n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":11}],11:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar fn = require('./fn');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, signature_pattern, macro, macro_context) {\n\n    var signature_pattern = new RegularExpression(signature_pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var _this = this;\n\n    var init = function(signature, signature_pattern) {\n        _this.signature = normalise(signature);\n    }\n\n    this.is_identified_by = function(other_signature) {\n        return this.signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context().merge(macro_context).merge(scenario_context);\n        var args = signature_pattern.groups(step);\n        event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n        fn.invoke(macro, context.properties, args.concat(next));\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    var normalise = function(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    this.toString = function() {\n        return this.signature;\n    };\n\n    init(signature, signature_pattern);\n};\n\nmodule.exports = Macro;\n\n},{\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":14}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 \nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();        \n        return result;\n    };  \n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {            \n            var groups = match.slice(1, match.length);\n            results.push(groups)\n            match = regexp.global && regexp.exec(text)\n        }\n        this.reset();\n        return results.flatten();        \n    };   \n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };    \n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };    \n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\n// Provides a repetitive interface, i.e. new Yadda().yadda().yadda() to the Yadda Interpreter\nvar Yadda = function(libraries, interpreter_context) {\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length == 0) return this;\n        if (arguments.length == 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    this.toString = function() {\n        return \"Yadda 0.9.9 Copyright 2010 Acuminous Ltd / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":14}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        }\n    };\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    };\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    };\n\n    function noop() {};\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    };\n\n    return {\n        noop: noop,\n        async_noop: asynchronize(null, noop), \n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],\"yadda\":[function(require,module,exports){\nmodule.exports=require('3V0FPO');\n},{}],\"3V0FPO\":[function(require,module,exports){\nmodule.exports = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),    \n    FileSearch: require('./FileSearch'),\n    localisation: require('./localisation/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index')\n};\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":10,\"./Yadda\":13,\"./localisation/index\":23,\"./parsers/index\":26,\"./plugins/index\":29,\"./shims/index\":30}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '[Ss]cenario',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: 'Pending',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n},{\"./Language\":19}],18:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: 'En attente',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given },\n        get etantdonnees() { return this.given },\n        get etantdonnee() { return this.given },\n        get etantdonne() { return this.given },\n        get quand() { return this.when },\n        get lorsque() { return this.when },\n        get alors() { return this.then }\n    };\n    \n    return new Language('French', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    var signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] == undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n},{\"../Array\":1,\"../Library\":10}],20:[function(require,module,exports){\n﻿/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: 'Avventer',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given },\n        get når() { return this.when },\n        get så() { return this.then }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":19}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: 'Brig',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given },\n        get whence() { return this.when },\n        get thence() { return this.then }        \n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":19}],22:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n    \n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: 'Pendiente',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n        \n        _steps: [\n            'given', 'when', 'then', \n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given },\n        get sean() { return this.given },\n        get dado() { return this.given },\n        get dada() { return this.given },\n        get dados() { return this.given },\n        get dadas() { return this.given },\n        get cuando() { return this.when },\n        get si() { return this.when },\n        get entonces() { return this.then }\n    };\n    \n    return new Language('Spanish', vocabulary);\n})();\n\n\n\n},{\"./Language\":19}],23:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = {\n    English: require('./English'),\n    Spanish: require('./Spanish'),\n    French: require('./French'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Language: require('./Language')\n}\n},{\"./English\":17,\"./French\":18,\"./Language\":19,\"./Norwegian\":20,\"./Pirate\":21,\"./Spanish\":22}],24:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar English = require('../localisation/English');\n\nvar FeatureParser = function(language) {\n\n    var language = language || English;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^\\\\s*([^\\\\s].*)', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}')\n    var BLANK_REGEX = new RegExp('^\\\\s*$');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^@([^=]*)=(.*)$');\n\n    var specification = undefined;\n    var comment = undefined;\n    var line = undefined;\n    var line_number = 0;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n        line_number = 0;\n    };\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    };\n\n    function parse_line(line, index) {\n        var match;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;        \n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: true });\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: match[1], value: match[2] });\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1]);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1]);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples');\n            if (match = BLANK_REGEX.test(line)) return specification.handle('Blank');\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1]);\n        } catch (e) {\n            throw new Error('Error parsing line ' + (index  + 1) + ', \"' + line + '\".\\n' + e.message);\n        };\n    };\n}\n\nvar Handlers = function(handlers) {\n\n    this.register = function(event, handler) {\n        handlers[event] = handler;\n    };\n\n    this.unregister = function(event) {\n        delete handlers[event];\n    };\n\n    this.find = function(event) {\n        if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n        return { handle: handlers[event.toLowerCase()] };\n    };\n};\n\nvar Specification = function() {\n\n    var current_element = this;\n    var feature = undefined;\n    var feature_annotations = {};\n    var handlers = new Handlers({\n        text: fn.noop,\n        blank: fn.noop,        \n        annotation: stash_annotation,\n        feature: start_feature,\n        scenario: start_scenario\n    });\n\n    function stash_annotation(event, annotation) {\n        feature_annotations[annotation.key] = annotation.value;\n        feature_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function start_feature(event, title) {\n        return feature = new Feature(title, feature_annotations);\n    };\n\n    function start_scenario(event, title) {\n        start_feature();\n        return feature.on(event, title);\n    };\n\n    this.handle = function(event, data) {\n        current_element = current_element.on(event, data);\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;        \n    };\n\n    this.export = function() {\n        if (!feature) throw new Error('A feature must contain one or more scenarios');\n        return feature.export();\n    };\n};\n\nvar Feature = function(title, annotations) {\n\n    var description = [];\n    var scenarios = [];\n    var scenario_annotations = {};      \n    var handlers = new Handlers({\n        text: capture_description,\n        blank: end_description,        \n        annotation: stash_annotation,        \n        scenario: start_scenario\n    }); \n    var _this = this;\n\n    function stash_annotation(event, annotation) {\n        scenario_annotations[annotation.key] = annotation.value;\n        scenario_annotations[annotation.key.toLowerCase().replace(/\\W/g, '_')] = annotation.value;\n    };\n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.unregister('text');\n        handlers.register('blank', fn.noop);\n    };\n\n    function start_scenario(event, title) {\n        var scenario = new Scenario(title, scenario_annotations, _this);\n        scenarios.push(scenario);\n        scenario_annotations = {};        \n        return scenario;\n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        return {\n            title: title,\n            annotations: annotations,\n            description: description,\n            scenarios: $(scenarios).collect(function(scenario) {\n                return scenario.export();\n            }).flatten().naked()\n        };        \n    };\n};\n\nvar Scenario = function(title, annotations, feature) {\n\n    var description = [];\n    var steps = [];\n    var examples = undefined;\n    var handlers = new Handlers({\n        text: capture_description,        \n        blank: end_description,\n        annotation: start_scenario,\n        scenario: start_scenario,\n        examples: start_examples\n    }); \n    var _this = this;  \n\n    function capture_description(event, text) {\n        description.push(text);\n    };\n\n    function end_description() {\n        handlers.register('text', capture_step);\n        handlers.register('blank', fn.noop);\n    };\n\n    function capture_step(event, text) {\n        steps.push(text);\n    }\n\n    function start_scenario(event, data) {\n        validate();\n        return feature.on(event, data);\n    };  \n\n    function start_examples(event, data) {\n        validate();\n        return examples = new Examples(_this);\n    };\n\n    function validate() {\n        if (steps.length == 0) throw new Error('Scenario requires one or more steps');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.export = function() {\n        validate();\n        var result = {\n            title: title,\n            annotations: annotations,\n            description: description,\n            steps: steps\n        };\n        return examples ? examples.expand(result) : result;\n    };\n};\n\nvar Examples = function(scenario) {\n\n    var SURROUNDING_WHITESPACE_REGEX = /^\\s+|\\s+$/g;\n\n    var headings = [];\n    var examples = $();\n    var handlers = new Handlers({\n        text: capture_headings,        \n        blank: fn.noop,\n        annotation: start_scenario,\n        scenario: start_scenario,\n    });\n\n    function capture_headings(event, data) {\n        handlers.register('text', capture_example);\n        headings = split(data).collect(function(column) {\n            return column.replace(SURROUNDING_WHITESPACE_REGEX, '');\n        }).naked();\n    };\n\n    function capture_example(event, data) {\n        var fields = split(data, headings.length);\n        var example = {};\n        fields.each(function(field, index) {\n            example[headings[index]] = field.replace(SURROUNDING_WHITESPACE_REGEX, '');            \n        });\n        examples.push(example);\n    };\n\n    function split(row, number_of_fields) {\n        var fields = $(row.split('|'));\n        if (number_of_fields != undefined && number_of_fields != fields.length) {\n            throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);                    \n        }\n        return fields;\n    };\n\n    function start_scenario(event, data) {\n        validate();\n        return scenario.on(event, data);\n    };\n\n    function validate() {\n        if (headings.length == 0) throw new Error('Examples table requires one or more headings');\n        if (examples.length == 0) throw new Error('Examples table requires one or more rows');        \n    };\n\n    this.on = function(event, data) {\n        return handlers.find(event).handle(event, data) || this;\n    };\n\n    this.expand = function(scenario) {\n        validate();\n        return examples.collect(function(example) {\n            return {\n                title: substitute(example, scenario.title),\n                annotations: scenario.annotations,\n                description: substitute(example, scenario.description),\n                steps: substitute(example, scenario.steps)\n            };            \n        }).naked();\n    };\n\n    function substitute(example, lines) {\n        return $(lines).collect(function(line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\[\\\\s*' + heading + '\\\\s*\\\\]', 'g'), example[heading]);\n            };\n            return line;\n        }).naked();\n    }\n};\n\nmodule.exports = FeatureParser;\n},{\"../Array\":1,\"../fn\":14,\"../localisation/English\":17}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n},{\"../Array\":1}],26:[function(require,module,exports){\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser')\n}\n},{\"./FeatureParser\":24,\"./StepParser\":25}],27:[function(require,module,exports){\nvar global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};if (!module.client) {   \n    var fs = require('fs');\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script == undefined) return this;\n        yadda.yadda(script, ctx);\n    }\n};\n\n},{\"fs\":35,\"yadda\":\"3V0FPO\"}],28:[function(require,module,exports){\nif (!module.client) {\n\tvar fs = require('fs');\n}\nvar English = require('../localisation/English');\nvar FeatureParser = require('../parsers/FeatureParser');\nvar $ = require('../Array');\n\nmodule.exports = function(options) {\n\n    var options = options || {};\n    var language = options.language || English;\n    var parser = options.parser || new FeatureParser(language);\n    var mode = options.mode || 'async';\n\tif (module.client) {\n\t\tvar feature = function (text, next) {\n\t\t\tparser.parse(text, function(feature) {\n\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\tnext(feature)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t} else {\n\t\tvar feature = function (filenames, next) {\n\t\t\t$(filenames).each(function(filename) {\n\t\t\t\tvar text = fs.readFileSync(filename, 'utf8');\n\t\t\t\tparser.parse(text, function(feature) {\n\t\t\t\t\tvar _describe = feature.annotations[language.localise('pending')] ? xdescribe : describe;\n\t\t\t\t\t_describe(feature.title || filename, function() {\n\t\t\t\t\t\tnext(feature)\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t}\n\n    function async_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function(done) {\n                next(scenario, done)\n            });\n        });\n    };\n\n    function sync_scenarios(scenarios, next) {\n        $(scenarios).each(function(scenario) {\n            var _it = scenario.annotations[language.localise('pending')] ? xit : it;\n            _it(scenario.title, function() {\n                next(scenario)\n            });\n        });\n    };\n\n\tif (typeof GLOBAL !== 'undefined') {\n\t\tGLOBAL.features = GLOBAL.feature = feature;\n\t\tGLOBAL.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\twindow.features = window.feature = feature;\n\t\twindow.scenarios = mode == 'async' ? async_scenarios : sync_scenarios;\n\t}\n};\n\n},{\"../Array\":1,\"../localisation/English\":17,\"../parsers/FeatureParser\":24,\"fs\":35}],29:[function(require,module,exports){\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: require('./MochaPlugin'),\n    jasmine: require('./MochaPlugin')\n}\n},{\"./CasperPlugin\":27,\"./MochaPlugin\":28}],30:[function(require,module,exports){\nvar process=require(\"__browserify_process\"),global=typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    var shims = {\n        node: function() {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            }\n        },\n        phantom: function() {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            }\n        }\n    }\n\n    function is_node() {\n        return typeof global != 'undefined' &&\n               typeof global.process != 'undefined' &&\n               global.process.title == 'node';\n    }\n\n    function is_phantom() {\n        return typeof phantom;\n    }\n\n    function get_shim() {\n        if (is_node()) return shims.node();\n\n        if (is_phantom()) return shims.phantom();\n        throw new Error('Unsupported Platform');\n    }\n\n    return get_shim();\n})();\n\n},{\"./phantom-fs\":31,\"./phantom-path\":32,\"./phantom-process\":33,\"__browserify_process\":38,\"fs\":35,\"path\":36}],31:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        }\n    };\n\n    return fs;\n})();\n\n},{\"fs\":35}],32:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    };\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":35,\"path\":36}],33:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    if (module.client) {\n        // Running in browser, not via node\n        return {}; // short-circuit;\n    }\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":35}],34:[function(require,module,exports){\n\n\n//\n// The shims in this file are not fully implemented shims for the ES5\n// features, but do work for the particular usecases there is in\n// the other modules.\n//\n\nvar toString = Object.prototype.toString;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// Array.isArray is supported in IE9\nfunction isArray(xs) {\n  return toString.call(xs) === '[object Array]';\n}\nexports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;\n\n// Array.prototype.indexOf is supported in IE9\nexports.indexOf = function indexOf(xs, x) {\n  if (xs.indexOf) return xs.indexOf(x);\n  for (var i = 0; i < xs.length; i++) {\n    if (x === xs[i]) return i;\n  }\n  return -1;\n};\n\n// Array.prototype.filter is supported in IE9\nexports.filter = function filter(xs, fn) {\n  if (xs.filter) return xs.filter(fn);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    if (fn(xs[i], i, xs)) res.push(xs[i]);\n  }\n  return res;\n};\n\n// Array.prototype.forEach is supported in IE9\nexports.forEach = function forEach(xs, fn, self) {\n  if (xs.forEach) return xs.forEach(fn, self);\n  for (var i = 0; i < xs.length; i++) {\n    fn.call(self, xs[i], i, xs);\n  }\n};\n\n// Array.prototype.map is supported in IE9\nexports.map = function map(xs, fn) {\n  if (xs.map) return xs.map(fn);\n  var out = new Array(xs.length);\n  for (var i = 0; i < xs.length; i++) {\n    out[i] = fn(xs[i], i, xs);\n  }\n  return out;\n};\n\n// Array.prototype.reduce is supported in IE9\nexports.reduce = function reduce(array, callback, opt_initialValue) {\n  if (array.reduce) return array.reduce(callback, opt_initialValue);\n  var value, isValueSet = false;\n\n  if (2 < arguments.length) {\n    value = opt_initialValue;\n    isValueSet = true;\n  }\n  for (var i = 0, l = array.length; l > i; ++i) {\n    if (array.hasOwnProperty(i)) {\n      if (isValueSet) {\n        value = callback(value, array[i], i, array);\n      }\n      else {\n        value = array[i];\n        isValueSet = true;\n      }\n    }\n  }\n\n  return value;\n};\n\n// String.prototype.substr - negative index don't work in IE8\nif ('ab'.substr(-1) !== 'b') {\n  exports.substr = function (str, start, length) {\n    // did we get a negative start, calculate how much it is from the beginning of the string\n    if (start < 0) start = str.length + start;\n\n    // call the original function\n    return str.substr(start, length);\n  };\n} else {\n  exports.substr = function (str, start, length) {\n    return str.substr(start, length);\n  };\n}\n\n// String.prototype.trim is supported in IE9\nexports.trim = function (str) {\n  if (str.trim) return str.trim();\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n// Function.prototype.bind is supported in IE9\nexports.bind = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var fn = args.shift();\n  if (fn.bind) return fn.bind.apply(fn, args);\n  var self = args.shift();\n  return function () {\n    fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));\n  };\n};\n\n// Object.create is supported in IE9\nfunction create(prototype, properties) {\n  var object;\n  if (prototype === null) {\n    object = { '__proto__' : null };\n  }\n  else {\n    if (typeof prototype !== 'object') {\n      throw new TypeError(\n        'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n      );\n    }\n    var Type = function () {};\n    Type.prototype = prototype;\n    object = new Type();\n    object.__proto__ = prototype;\n  }\n  if (typeof properties !== 'undefined' && Object.defineProperties) {\n    Object.defineProperties(object, properties);\n  }\n  return object;\n}\nexports.create = typeof Object.create === 'function' ? Object.create : create;\n\n// Object.keys and Object.getOwnPropertyNames is supported in IE9 however\n// they do show a description and number property on Error objects\nfunction notObject(object) {\n  return ((typeof object != \"object\" && typeof object != \"function\") || object === null);\n}\n\nfunction keysShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.keys called on a non-object\");\n  }\n\n  var result = [];\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// getOwnPropertyNames is almost the same as Object.keys one key feature\n//  is that it returns hidden properties, since that can't be implemented,\n//  this feature gets reduced so it just shows the length property on arrays\nfunction propertyShim(object) {\n  if (notObject(object)) {\n    throw new TypeError(\"Object.getOwnPropertyNames called on a non-object\");\n  }\n\n  var result = keysShim(object);\n  if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {\n    result.push('length');\n  }\n  return result;\n}\n\nvar keys = typeof Object.keys === 'function' ? Object.keys : keysShim;\nvar getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?\n  Object.getOwnPropertyNames : propertyShim;\n\nif (new Error().hasOwnProperty('description')) {\n  var ERROR_PROPERTY_FILTER = function (obj, array) {\n    if (toString.call(obj) === '[object Error]') {\n      array = exports.filter(array, function (name) {\n        return name !== 'description' && name !== 'number' && name !== 'message';\n      });\n    }\n    return array;\n  };\n\n  exports.keys = function (object) {\n    return ERROR_PROPERTY_FILTER(object, keys(object));\n  };\n  exports.getOwnPropertyNames = function (object) {\n    return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));\n  };\n} else {\n  exports.keys = keys;\n  exports.getOwnPropertyNames = getOwnPropertyNames;\n}\n\n// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements\nfunction valueObject(value, key) {\n  return { value: value[key] };\n}\n\nif (typeof Object.getOwnPropertyDescriptor === 'function') {\n  try {\n    Object.getOwnPropertyDescriptor({'a': 1}, 'a');\n    exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n  } catch (e) {\n    // IE8 dom element issue - use a try catch and default to valueObject\n    exports.getOwnPropertyDescriptor = function (value, key) {\n      try {\n        return Object.getOwnPropertyDescriptor(value, key);\n      } catch (e) {\n        return valueObject(value, key);\n      }\n    };\n  }\n} else {\n  exports.getOwnPropertyDescriptor = valueObject;\n}\n\n},{}],35:[function(require,module,exports){\n\n// not implemented\n// The reason for having an empty file and not throwing is to allow\n// untraditional implementation of this module.\n\n},{}],36:[function(require,module,exports){\nvar process=require(\"__browserify_process\");// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar util = require('util');\nvar shims = require('_shims');\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (!util.isString(path)) {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = shims.substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(shims.filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(shims.filter(paths, function(p, index) {\n    if (!util.isString(p)) {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\n},{\"__browserify_process\":38,\"_shims\":34,\"util\":37}],37:[function(require,module,exports){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar shims = require('_shims');\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (!isString(f)) {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j':\n        try {\n          return JSON.stringify(args[i++]);\n        } catch (_) {\n          return '[Circular]';\n        }\n      default:\n        return x;\n    }\n  });\n  for (var x = args[i]; i < len; x = args[++i]) {\n    if (isNull(x) || !isObject(x)) {\n      str += ' ' + x;\n    } else {\n      str += ' ' + inspect(x);\n    }\n  }\n  return str;\n};\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n  // default options\n  var ctx = {\n    seen: [],\n    stylize: stylizeNoColor\n  };\n  // legacy...\n  if (arguments.length >= 3) ctx.depth = arguments[2];\n  if (arguments.length >= 4) ctx.colors = arguments[3];\n  if (isBoolean(opts)) {\n    // legacy...\n    ctx.showHidden = opts;\n  } else if (opts) {\n    // got an \"options\" object\n    exports._extend(ctx, opts);\n  }\n  // set default options\n  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n  if (isUndefined(ctx.depth)) ctx.depth = 2;\n  if (isUndefined(ctx.colors)) ctx.colors = false;\n  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n  if (ctx.colors) ctx.stylize = stylizeWithColor;\n  return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n  'bold' : [1, 22],\n  'italic' : [3, 23],\n  'underline' : [4, 24],\n  'inverse' : [7, 27],\n  'white' : [37, 39],\n  'grey' : [90, 39],\n  'black' : [30, 39],\n  'blue' : [34, 39],\n  'cyan' : [36, 39],\n  'green' : [32, 39],\n  'magenta' : [35, 39],\n  'red' : [31, 39],\n  'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n  'special': 'cyan',\n  'number': 'yellow',\n  'boolean': 'yellow',\n  'undefined': 'grey',\n  'null': 'bold',\n  'string': 'green',\n  'date': 'magenta',\n  // \"name\": intentionally not styling\n  'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n  var style = inspect.styles[styleType];\n\n  if (style) {\n    return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n           '\\u001b[' + inspect.colors[style][1] + 'm';\n  } else {\n    return str;\n  }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n  return str;\n}\n\n\nfunction arrayToHash(array) {\n  var hash = {};\n\n  shims.forEach(array, function(val, idx) {\n    hash[val] = true;\n  });\n\n  return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (ctx.customInspect &&\n      value &&\n      isFunction(value.inspect) &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (!isString(ret)) {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // Look up the keys of the object.\n  var keys = shims.keys(value);\n  var visibleKeys = arrayToHash(keys);\n\n  if (ctx.showHidden) {\n    keys = shims.getOwnPropertyNames(value);\n  }\n\n  // Some type of object without properties can be shortcutted.\n  if (keys.length === 0) {\n    if (isFunction(value)) {\n      var name = value.name ? ': ' + value.name : '';\n      return ctx.stylize('[Function' + name + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (isFunction(value)) {\n    var n = value.name ? ': ' + value.name : '';\n    base = ' [Function' + n + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    base = ' ' + formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  if (isUndefined(value))\n    return ctx.stylize('undefined', 'undefined');\n  if (isString(value)) {\n    var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                             .replace(/'/g, \"\\\\'\")\n                                             .replace(/\\\\\"/g, '\"') + '\\'';\n    return ctx.stylize(simple, 'string');\n  }\n  if (isNumber(value))\n    return ctx.stylize('' + value, 'number');\n  if (isBoolean(value))\n    return ctx.stylize('' + value, 'boolean');\n  // For some reason typeof null is \"object\", so special case here.\n  if (isNull(value))\n    return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (hasOwnProperty(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n\n  shims.forEach(keys, function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str, desc;\n  desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n  if (desc.get) {\n    if (desc.set) {\n      str = ctx.stylize('[Getter/Setter]', 'special');\n    } else {\n      str = ctx.stylize('[Getter]', 'special');\n    }\n  } else {\n    if (desc.set) {\n      str = ctx.stylize('[Setter]', 'special');\n    }\n  }\n\n  if (!hasOwnProperty(visibleKeys, key)) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (shims.indexOf(ctx.seen, desc.value) < 0) {\n      if (isNull(recurseTimes)) {\n        str = formatValue(ctx, desc.value, null);\n      } else {\n        str = formatValue(ctx, desc.value, recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (isUndefined(name)) {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = shims.reduce(output, function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n  return shims.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n  return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n  return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n  return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n  return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n  return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n  return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n  return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n  return isObject(e) && objectToString(e) === '[object Error]';\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n  return arg === null ||\n         typeof arg === 'boolean' ||\n         typeof arg === 'number' ||\n         typeof arg === 'string' ||\n         typeof arg === 'symbol' ||  // ES6 symbol\n         typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nfunction isBuffer(arg) {\n  return arg && typeof arg === 'object'\n    && typeof arg.copy === 'function'\n    && typeof arg.fill === 'function'\n    && typeof arg.binarySlice === 'function'\n  ;\n}\nexports.isBuffer = isBuffer;\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n *     prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = shims.create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nexports._extend = function(origin, add) {\n  // Don't do anything if add isn't an object\n  if (!add || !isObject(add)) return origin;\n\n  var keys = shims.keys(add);\n  var i = keys.length;\n  while (i--) {\n    origin[keys[i]] = add[keys[i]];\n  }\n  return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n},{\"_shims\":34}],38:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}]},{},[\"3V0FPO\"])\n(3V0FPO)\n});\n;"
  },
  {
    "path": "dist/yadda-umd-1.0.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] == item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    /* jslint shadow: true */\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() != this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n    var _this = this;\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length == 1) return this.send(event_name, {});\n        if (arguments.length == 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar process = shims.process;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    /* jslint shadow: true */\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    /* jslint shadow: true */\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    /* jslint shadow: true */\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var slice = Array.prototype.slice;\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* jslint shadow: true */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature == normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n/* jslint browser: true */\n/* jslint phantom: true */\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n    }\n\n    function is_node() {\n        return typeof process != 'undefined' &&\n               typeof global != 'undefined' &&\n               typeof __dirname != 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window != 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom != 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window != 'undefined' && typeof window.__karma__ != 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() == other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n    var _this = this;\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.0.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n},{}],16:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n},{}],17:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n},{}],19:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n},{}],20:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n},{}],21:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n    var watermark = 0;\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n/* jslint node: true */\r\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n/*\n* Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Author: Marat Dyatko\n * https://github.com/vectart\n *\n * Inspired by Gherkin vocabulary\n * https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json\n *\n * Also considered syntax highlight of Cucumber Sublime bundle\n * https://github.com/drewda/cucumber-sublime-bundle/blob/master/Cucumber%20Plain%20Text%20Feature.tmLanguage\n */\n\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n/* -*- coding: utf-8 -*-\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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 /* jslint node: true */\n \"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* jslint shadow: true */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        /* jslint boss: true */\n        var match;\n        var line_number = index + 1;\n        try {\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        /* jslint shadow: true */\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background,\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            /* jslint boss: true */\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n        var _this = this;\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields != fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length == 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    /* jslint shadow: true */\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length == 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        /* jslint shadow: true */\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n    };\n\n    var score = function() {\n\n        /*jslint boss: true */\n        if (s1 == s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] == s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1,\"../fn\":22}],47:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory != directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize != \"function\" || typeof path.dirname != \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name != '.' && name != '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process != 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n/*\n * Copyright 2010 Acuminous Ltd / Energized Work Ltd\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/* jslint node: true */\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.0.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.0.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],47:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.1.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.1.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],47:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.1.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.1.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],47:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.2.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":45,\"./scores/MultiScore\":46,\"./scores/SameLibraryScore\":47}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":48}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":57}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.2.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34}],36:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":48,\"./FeatureParser\":37}],37:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":35}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],39:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":36,\"./FeatureParser\":37,\"./StepParser\":38}],40:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":48,\"yadda\":\"yadda\"}],41:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":40,\"./mocha/ScenarioLevelPlugin\":43,\"./mocha/StepLevelPlugin\":44}],42:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":35,\"../../parsers/FeatureFileParser\":36}],43:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":42}],45:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],46:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],47:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],48:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":49,\"./karma-path\":50,\"./karma-process\":51,\"./phantom-fs\":52,\"./phantom-path\":53,\"./phantom-process\":54,\"_process\":57,\"fs\":55,\"path\":56}],49:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":50}],50:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":56}],51:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":49}],52:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":55}],53:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":55,\"path\":56}],54:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":55}],55:[function(require,module,exports){\n\n},{}],56:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":57}],57:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":35,\"./parsers/index\":39,\"./plugins/index\":41,\"./shims/index\":48}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.3.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.3.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: end_description,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function end_description(event, text, line_number) {\n            handlers.unregister('text');\n            handlers.register('blank', fn.noop);\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.3.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.3.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.4.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.4.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.5.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.5.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-1.5.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 1.5.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-2.0.0.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libraries) {\n        libraries.push_all(libraries);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 2.0.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        var leading_spaces = '^(?:\\\\s)*';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-2.0.1.js",
    "content": "require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libs) {\n        libraries.push_all(libs);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 2.0.1 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        var leading_spaces = '^(?:\\\\s)*';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// resolves . and .. elements in a path array with directory names there\n// must be no slashes, empty elements, or device names (c:\\) in the array\n// (so also no leading and trailing slashes - it does not distinguish\n// relative and absolute paths)\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length - 1; i >= 0; i--) {\n    var last = parts[i];\n    if (last === '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nvar splitPathRe =\n    /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\nvar splitPath = function(filename) {\n  return splitPathRe.exec(filename).slice(1);\n};\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\n  var resolvedPath = '',\n      resolvedAbsolute = false;\n\n  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n    var path = (i >= 0) ? arguments[i] : process.cwd();\n\n    // Skip empty and invalid entries\n    if (typeof path !== 'string') {\n      throw new TypeError('Arguments to path.resolve must be strings');\n    } else if (!path) {\n      continue;\n    }\n\n    resolvedPath = path + '/' + resolvedPath;\n    resolvedAbsolute = path.charAt(0) === '/';\n  }\n\n  // At this point the path should be resolved to a full absolute path, but\n  // handle relative paths to be safe (might happen when process.cwd() fails)\n\n  // Normalize the path\n  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\n  var isAbsolute = exports.isAbsolute(path),\n      trailingSlash = substr(path, -1) === '/';\n\n  // Normalize the path\n  path = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path && !isAbsolute) {\n    path = '.';\n  }\n  if (path && trailingSlash) {\n    path += '/';\n  }\n\n  return (isAbsolute ? '/' : '') + path;\n};\n\n// posix version\nexports.isAbsolute = function(path) {\n  return path.charAt(0) === '/';\n};\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    if (typeof p !== 'string') {\n      throw new TypeError('Arguments to path.join must be strings');\n    }\n    return p;\n  }).join('/'));\n};\n\n\n// path.relative(from, to)\n// posix version\nexports.relative = function(from, to) {\n  from = exports.resolve(from).substr(1);\n  to = exports.resolve(to).substr(1);\n\n  function trim(arr) {\n    var start = 0;\n    for (; start < arr.length; start++) {\n      if (arr[start] !== '') break;\n    }\n\n    var end = arr.length - 1;\n    for (; end >= 0; end--) {\n      if (arr[end] !== '') break;\n    }\n\n    if (start > end) return [];\n    return arr.slice(start, end - start + 1);\n  }\n\n  var fromParts = trim(from.split('/'));\n  var toParts = trim(to.split('/'));\n\n  var length = Math.min(fromParts.length, toParts.length);\n  var samePartsLength = length;\n  for (var i = 0; i < length; i++) {\n    if (fromParts[i] !== toParts[i]) {\n      samePartsLength = i;\n      break;\n    }\n  }\n\n  var outputParts = [];\n  for (var i = samePartsLength; i < fromParts.length; i++) {\n    outputParts.push('..');\n  }\n\n  outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n  return outputParts.join('/');\n};\n\nexports.sep = '/';\nexports.delimiter = ':';\n\nexports.dirname = function(path) {\n  var result = splitPath(path),\n      root = result[0],\n      dir = result[1];\n\n  if (!root && !dir) {\n    // No dirname whatsoever\n    return '.';\n  }\n\n  if (dir) {\n    // It has a dirname, strip trailing slash\n    dir = dir.substr(0, dir.length - 1);\n  }\n\n  return root + dir;\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPath(path)[2];\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext && f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPath(path)[3];\n};\n\nfunction filter (xs, f) {\n    if (xs.filter) return xs.filter(f);\n    var res = [];\n    for (var i = 0; i < xs.length; i++) {\n        if (f(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n// String.prototype.substr - negative index don't work in IE8\nvar substr = 'ab'.substr(-1) === 'b'\n    ? function (str, start, len) { return str.substr(start, len) }\n    : function (str, start, len) {\n        if (start < 0) start = str.length + start;\n        return str.substr(start, len);\n    }\n;\n\n}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-2.1.0.js",
    "content": "require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\n\nmodule.exports = function(obj) {\n\n    function ensure_array(obj) {\n        var array = obj ? [].concat(obj) : [];\n        array.in_array = fn.curry(array, in_array, array);\n        array.each = fn.curry(array, each, array);\n        array.each_async = fn.curry(array, each_async, array);\n        array.collect = fn.curry(array, collect, array);\n        array.collect_async = fn.curry(array, collect_async, array);\n        array.flatten = fn.curry(array, flatten, array);\n        array.inject = fn.curry(array, inject, array);\n        array.push_all = fn.curry(array, push_all, array);\n        array.fill = fn.curry(array, fill, array);\n        array.find_all = fn.curry(array, find_all, array);\n        array.find = fn.curry(array, find, array);\n        array.last = fn.curry(array, last, array);\n        array.naked = fn.curry(array, naked, array);\n        return array;\n    }\n\n    function is_array(obj) {\n        return Object.prototype.toString.call(obj) === '[object Array]';\n    }\n\n    function in_array(items, item) {\n        for (var i = 0; i < items.length; i++) {\n            if (items[i] === item) {\n                return true;\n            }\n        }\n    }\n\n    function flatten(items) {\n        if (!is_array(items)) return [items];\n        if (items.length === 0) return items;\n        var head = flatten(items[0]);\n        var tail = flatten(items.slice(1));\n        return ensure_array(head.concat(tail));\n    }\n\n    function each(items, iterator) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(items[i], i);\n        }\n        return result;\n    }\n\n    function each_async(items, iterator, callback) {\n        callback = callback || fn.noop;\n        if (!items.length) return callback();\n        var index = 0;\n        var iterate = function() {\n            iterator(items[index], index, function(err, result) {\n                if (err) return callback(err);\n                if (++index >= items.length) return callback(null, result);\n                iterate();\n            });\n        };\n        iterate();\n    }\n\n    function collect(items, iterator) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            results.push(iterator(items[i], i));\n        }\n        return results;\n    }\n\n    function collect_async(items, iterator, callback) {\n        var results = ensure_array();\n        each_async(items, function(item, index, each_callback) {\n            iterator(item, index, function(err) {\n                if (err) return each_callback(err);\n                results.push_all(Array.prototype.splice.call(arguments, 1));\n                each_callback();\n            });\n        }, function(err) {\n            if (err) return callback(err);\n            callback(null, results);\n        });\n    }\n\n    function inject(items, default_value, iterator) {\n        var result = default_value;\n        for (var i = 0; i < items.length; i++) {\n            result = iterator(result, items[i]);\n        }\n        return result;\n    }\n\n    function push_all(items, more_items) {\n        more_items = more_items ? [].concat(more_items) : [];\n        for (var i = 0; i < more_items.length; i++) {\n            items.push(more_items[i]);\n        }\n        return items;\n    }\n\n    function fill(items, item, num) {\n        for (var i = 0; i < num; i++) {\n            items.push(item);\n        }\n        return items;\n    }\n\n    function find_all(items, test) {\n        var results = ensure_array();\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                results.push(items[i]);\n            }\n        }\n        return results;\n    }\n\n    function find(items, test) {\n        var result;\n        for (var i = 0; i < items.length; i++) {\n            if (test(items[i], i)) {\n                result = items[i];\n                break;\n            }\n        }\n        return result;\n    }\n\n    function last(items) {\n        return items[items.length - 1];\n    }\n\n    function naked(items) {\n        return [].concat(items);\n    }\n\n    return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n\"use strict\";\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function(step, macros, last_macro) {\n\n    var results = [];\n\n    this.validate = function() {\n        if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n        if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n        return { step: step, valid: true, winner: this.winner() };\n    };\n\n    this.clear_winner = function() {\n        if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n        if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n        return this.winner();\n    };\n\n    function is_undefined() {\n        return results.length === 0;\n    }\n\n    function is_ambiguous() {\n        return (results.length > 1) && results[0].score.equals(results[1].score);\n    }\n\n    this.winner = function() {\n        return results[0].macro;\n    };\n\n    function winning_patterns() {\n        return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n    }\n\n    function rank(step, macros) {\n        results = macros.collect(function(macro) {\n            return {\n                macro: macro,\n                score: new MultiScore([\n                    new LevenshteinDistanceScore(step, macro.levenshtein_signature()),\n                    new SameLibraryScore(macro, last_macro)\n                ])\n            };\n        }).sort(by_ascending_score);\n    }\n\n    function by_ascending_score(a, b) {\n        return b.score.compare(a.score);\n    }\n\n    function by_winning_score(result) {\n        return result.score.equals(results[0].score);\n    }\n\n    function macro_signatures(result) {\n        return result.macro.toString();\n    }\n\n    rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n\"use strict\";\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function(properties) {\n\n    // I was previously getting some weird errors using instanceof to determine if\n    // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n    this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n    this.properties = {};\n\n    this.merge = function(other) {\n        if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n        return new Context(this.properties)._merge(other);\n    };\n\n    this._merge = function(other) {\n        for (var key in other) { this.properties[key] = other[key]; }\n        return this;\n    };\n\n    this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function(prefix) {\n\n    // eslint-disable-next-line no-redeclare\n    var prefix = prefix || '$';\n    var definitions = {};\n    var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n    var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n    var _this = this;\n\n    this.define = function(term, pattern, converters) {\n        if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n        if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n        if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n        if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n        definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n        return this;\n    };\n\n    this.merge = function(other) {\n        if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n        return new Dictionary(prefix)._merge(this)._merge(other);\n    };\n\n    this._merge = function(other) {\n        other.each(function(term, definition) {\n            _this.define(term, definition.pattern);\n        });\n        return this;\n    };\n\n    this._prefix = function() {\n        return prefix;\n    };\n\n    this.each = function(callback) {\n        for (var term in definitions) {\n            callback(term, definitions[term]);\n        }\n    };\n\n    this.expand = function(signature, already_expanding) {\n        var text = normalise(signature);\n        return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) }\n                                   : { pattern: text, converters: get_converters(text) };\n    };\n\n    function expand_sub_terms(text, already_expanding) {\n        return get_sub_terms(text).each(function(sub_term) {\n            if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n            var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n            text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n            return text;\n        });\n    }\n\n    function get_sub_terms(text) {\n        return term_grouping_pattern.groups(text);\n    }\n\n    function expand_sub_term(sub_term, already_expanding) {\n        var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n        return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n    }\n\n    function normalise(pattern) {\n        return pattern.toString().replace(/^\\/|\\/$/g, '');\n    }\n\n    function is_defined(term) {\n        return !!definitions[term];\n    }\n\n    function is_expandable(text) {\n        return term_grouping_pattern.test(text);\n    }\n\n    function is_compatible(converters, pattern) {\n        return count_converter_arguments(converters) === count_matching_groups(pattern);\n    }\n\n    function get_converters(text) {\n        return $(text.split(term_splitting_pattern)).inject($(), function(converters, fragment) {\n            return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment)\n                                                               : get_matching_group_converters(fragment));\n        });\n    }\n\n    function get_matching_group_converters(text) {\n        return $().fill(pass_through_converter, count_matching_groups(text));\n    }\n\n    function get_sub_term_converters(text) {\n        return get_sub_terms(text).inject($(), function(converters, sub_term) {\n            return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters)\n                                        : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n        });\n    }\n\n    function count_matching_groups(pattern) {\n        return new RegExp(pattern + '|').exec('').length - 1;\n    }\n\n    function count_converter_arguments(converters) {\n        return $(converters).inject(0, function(sum, converter) {\n            return sum + converter.length - 1;\n        });\n    }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n\n    var event_handlers = $();\n\n    this.send = function(event_name, event_data, next) {\n        if (arguments.length === 1) return this.send(event_name, {});\n        if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n        notify_handlers(event_name, event_data);\n        next && next();\n        return this;\n    };\n\n    this.on = function(event_pattern, callback) {\n        event_handlers.push({ pattern: event_pattern, callback: callback });\n        return this;\n    };\n\n    var notify_handlers = function(event_name, event_data) {\n        find_handlers(event_name).each(function(callback) {\n            callback({ name: event_name, data: event_data });\n        });\n    };\n\n    var find_handlers = function(event_name) {\n        return event_handlers.find_all(function(handler) {\n            return new RegExp(handler.pattern).test(event_name);\n        }).collect(function(handler) {\n            return handler.callback;\n        });\n    };\n}\n\nfunction instance() {\n    return event_bus;\n}\n\nmodule.exports = {\n    instance: instance,\n    ON_SCENARIO: '__ON_SCENARIO__',\n    ON_STEP: '__ON_STEP__',\n    ON_EXECUTE: '__ON_EXECUTE__',\n    ON_DEFINE: '__ON_DEFINE__'\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n\"use strict\";\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function(directories) {\n    this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n\"use strict\";\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function(directories, patterns) {\n\n    // eslint-disable-next-line no-redeclare\n    var patterns = patterns || /.*/;\n\n    this.each = function(fn) {\n        this.list().forEach(fn);\n    };\n\n    this.list = function() {\n        return $(directories).inject($(), function(files, directory) {\n            return files.concat(list_files(directory).find_all(by_pattern));\n        });\n    };\n\n    var list_files = function(directory) {\n        return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n    };\n\n    var list_immediate_files = function(directory) {\n        return ls(directory).find_all(by_file);\n    };\n\n    var list_sub_directory_files = function(directory) {\n        return ls(directory).find_all(by_directory).inject($(), function(files, directory) {\n            return files.concat(list_files(directory));\n        });\n    };\n\n    var ls = function(directory) {\n        if (!fs.existsSync(directory)) return $();\n        return $(fs.readdirSync(directory)).collect(function(file) {\n            return path.join(directory, file);\n        });\n    };\n\n    var by_file = function(file) {\n        return !by_directory(file);\n    };\n\n    var by_directory = function(file) {\n        return fs.statSync(file).isDirectory();\n    };\n\n    var by_pattern = function(filename) {\n        return $(patterns).find(function(pattern) {\n            return new RegExp(pattern).test(filename);\n        });\n    };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n\"use strict\";\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function(libraries) {\n\n    // eslint-disable-next-line no-redeclare\n    var libraries = $(libraries);\n    var event_bus = EventBus.instance();\n    var last_macro;\n    var _this = this;\n\n    this.requires = function(libs) {\n        libraries.push_all(libs);\n        return this;\n    };\n\n    this.validate = function(scenario) {\n        var results = $(scenario).collect(function(step) {\n            var report = _this.rank_macros(step).validate();\n            last_macro = report.winner;\n            return report;\n        });\n        if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n    };\n\n    function by_invalid_step(result) {\n        return !result.valid;\n    }\n\n    function validation_report(result) {\n        return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n    }\n\n    this.interpret = function(scenario, scenario_context, next) {\n        scenario_context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n        var iterator = make_step_iterator(scenario_context, next);\n        $(scenario).each_async(iterator, next);\n    };\n\n    var make_step_iterator = function(scenario_context, next) {\n        var iterator = function(step, index, callback) {\n            _this.interpret_step(step, scenario_context, callback);\n        };\n        return next ? iterator : fn.asynchronize(null, iterator);\n    };\n\n    this.interpret_step = function(step, scenario_context, next) {\n        var context = new Context().merge(scenario_context);\n        event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n        var macro = this.rank_macros(step).clear_winner();\n        last_macro = macro;\n        macro.interpret(step, context || {}, next);\n    };\n\n    this.rank_macros = function(step) {\n        return new Competition(step, compatible_macros(step), last_macro);\n    };\n\n    var compatible_macros = function(step) {\n        return libraries.inject([], function(macros, library) {\n            return macros.concat(library.find_compatible_macros(step));\n        });\n    };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n\"use strict\";\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function(dictionary) {\n\n    // eslint-disable-next-line no-redeclare\n    var dictionary = dictionary || new Dictionary();\n    var macros = $();\n    var _this = this;\n\n    this.define = function(signatures, fn, macro_context, options) {\n        $(signatures).each(function(signature) {\n            define_macro(signature, fn, macro_context, options);\n        });\n        return this;\n    };\n\n    var define_macro = function(signature, fn, macro_context, options) {\n        if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n        macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n    };\n\n    this.get_macro = function(signature) {\n        return macros.find(function(other_macro) {\n            return other_macro.is_identified_by(signature);\n        });\n    };\n\n    this.find_compatible_macros = function(step) {\n        return macros.find_all(function(macro) {\n            return macro.can_interpret(step);\n        });\n    };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n\"use strict\";\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function(signature, parsed_signature, macro, macro_context, library, options) {\n\n    /* eslint-disable no-redeclare */\n    var signature = normalise(signature);\n    var signature_pattern = new RegularExpression(parsed_signature.pattern);\n    var macro = macro || fn.async_noop;\n    var event_bus = EventBus.instance();\n    var options = options || {};\n    /* eslint-enable no-redeclare */\n\n    this.library = library;\n\n    this.is_identified_by = function(other_signature) {\n        return signature === normalise(other_signature);\n    };\n\n    this.can_interpret = function(step) {\n        return signature_pattern.test(step);\n    };\n\n    this.interpret = function(step, scenario_context, next) {\n        var context = new Context({step:step}).merge(macro_context).merge(scenario_context);\n        convert(signature_pattern.groups(step), function(err, args) {\n            if (err) return next(err);\n            event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n            var result;\n            try {\n                result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n            } catch (err) {\n                if (next) return next(err);\n                throw err;\n            }\n            if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n            if (is_sync(args)) return next && next();\n        });\n    };\n\n    this.is_sibling = function(other_macro) {\n        return other_macro && other_macro.defined_in(library);\n    };\n\n    this.defined_in = function(other_library) {\n        return library === other_library;\n    };\n\n    this.levenshtein_signature = function() {\n        return signature_pattern.without_expressions();\n    };\n\n    this.toString = function() {\n        return signature;\n    };\n\n    function is_promise(result) {\n        if (options.mode) return options.mode === 'promise';\n        return result && result.then;\n    }\n\n    function is_sync(args) {\n        if (options.mode) return options.mode === 'sync';\n        return macro !== fn.async_noop && macro.length !== args.length + 1;\n    }\n\n    function normalise(signature) {\n        return new RegExp(signature).toString();\n    }\n\n    function convert(args, next) {\n        var index = 0;\n        return $(parsed_signature.converters).collect(function(converter) {\n            return function(callback) {\n                converter.apply(null, args.slice(index, index += converter.length - 1).concat(callback));\n            };\n        }).collect_async(function(converter, index, callback) {\n            converter(callback);\n        }, next);\n    }\n\n    event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){(function (){\n\"use strict\";\n\nmodule.exports = Platform;\n\nfunction Platform() {\n\n    function get_container() {\n        /* eslint-disable no-undef */\n        if (is_browser()) return window;\n        if (is_phantom()) return phantom;\n        if (is_node()) return global;\n        /* eslint-enable no-undef */\n    }\n\n    function is_node() {\n        return typeof process !== 'undefined' &&\n               typeof global !== 'undefined' &&\n               typeof __dirname !== 'undefined';\n    }\n\n    function is_browser() {\n        return typeof window !== 'undefined';\n    }\n\n    function is_phantom() {\n        return typeof phantom !== 'undefined';\n    }\n\n    function is_karma() {\n        return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n    }\n\n    return {\n        get_container: get_container,\n        is_node: is_node,\n        is_browser: is_browser,\n        is_phantom: is_phantom,\n        is_karma: is_karma\n    };\n\n}\n\n}).call(this)}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function(pattern_or_regexp) {\n\n    var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n    var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n    var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n    var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n    var non_word_tokens_pattern = /[^\\w\\s]/g;\n    var regexp = new RegExp(pattern_or_regexp);\n\n    this.test = function(text) {\n        var result = regexp.test(text);\n        this.reset();\n        return result;\n    };\n\n    this.groups = function(text) {\n        var results = $();\n        var match = regexp.exec(text);\n        while (match) {\n            var groups = match.slice(1, match.length);\n            results.push(groups);\n            match = regexp.global && regexp.exec(text);\n        }\n        this.reset();\n        return results.flatten();\n    };\n\n    this.reset = function() {\n        regexp.lastIndex = 0;\n        return this;\n    };\n\n    this.without_expressions = function() {\n        return regexp.source.replace(groups_pattern, '$1')\n                            .replace(sets_pattern, '$1')\n                            .replace(repetitions_pattern, '$1')\n                            .replace(regex_aliases_pattern, '$1')\n                            .replace(non_word_tokens_pattern, '');\n    };\n\n    this.equals = function(other) {\n        return this.toString() === other.toString();\n    };\n\n    this.toString = function() {\n        return \"/\" + regexp.source + \"/\";\n    };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n\n    trim: function trim(text) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    },\n    rtrim: function rtrim(text) {\n        return text.replace(/\\s+$/g, '');\n    },\n    isBlank: function isBlank(text) {\n        return /^\\s*$/g.test(text);\n    },\n    isNotBlank: function isNotBlank(text) {\n        return !this.isBlank(text);\n    },\n    indentation: function indentation(text) {\n        var match = /^(\\s*)/.exec(text);\n        return match && match[0].length || 0;\n    }\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n\"use strict\";\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function(libraries, interpreter_context) {\n\n    if (!(this instanceof Yadda)) {\n        return new Yadda(libraries, interpreter_context);\n    }\n\n    this.interpreter = new Interpreter(libraries);\n\n    this.requires = function(libraries) {\n        this.interpreter.requires(libraries);\n        return this;\n    };\n\n    this.yadda = function(scenario, scenario_context, next) {\n        if (arguments.length === 0) return this;\n        if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n        this.interpreter.validate(scenario);\n        this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n    };\n\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    this.run = this.yadda;\n\n    this.toString = function() {\n        return \"Yadda 2.1.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd\";\n    };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function date_converter(value, next) {\n    var converted = Date.parse(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n    return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function float_converter(value, next) {\n    var converted = parseFloat(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n    return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    date: require('./date-converter'),\n    integer: require('./integer-converter'),\n    float: require('./float-converter'),\n    list: require('./list-converter'),\n    table: require('./table-converter'),\n    pass_through: require('./pass-through-converter')\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function integer_converter(value, next) {\n    var converted = parseInt(value);\n    if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n    return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function list_converter(value, next) {\n    return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = function pass_through_converter(value, next) {\n    return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\n\nmodule.exports = function table_converter(value, next) {\n\n    var rows = value.split(/\\n/);\n    var headings = parse_headings(rows.shift());\n    var handler =  is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n    var table = $();\n\n    try {\n        $(rows).each(handler);\n        next(null, collapse(table));\n    } catch(err) {\n        next(err);\n    }\n\n    function handle_single_line_row(row) {\n        if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n        start_new_row();\n        parse_fields(row);\n    }\n\n    function handle_multiline_row(row) {\n        if (is_horizinal_separator(row)) return start_new_row();\n        parse_fields(row);\n    }\n\n    function parse_headings(row) {\n        return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).collect(function(value) {\n            return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n        }).naked();\n    }\n\n    function is_horizinal_separator(row) {\n        return DASH_REGEX.test(row);\n    }\n\n    function start_new_row() {\n        table.push({});\n    }\n\n    function parse_fields(row) {\n        var fields = table.last();\n        $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function(field, index) {\n            var column = headings[index].text;\n            var indentation = headings[index].indentation;\n            var text = StringUtils.rtrim(field.substr(indentation));\n            if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n            fields[column] = (fields[column] || []).concat(text);\n        });\n    }\n\n    function collapse(table) {\n        return table.collect(function(row) {\n            var new_row = {};\n            for (var heading in row) {\n                new_row[heading] = row[heading].join('\\n');\n            }\n            return new_row;\n        }).naked();\n    }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n\n    var slice = Array.prototype.slice;\n\n    function curry(ctx, fn) {\n        var args = slice.call(arguments, 2);\n        return function() {\n            return fn.apply(ctx, args.concat(slice.call(arguments)));\n        };\n    }\n\n    function invoke(fn, ctx, args) {\n        return fn.apply(ctx, args);\n    }\n\n    function is_function(object) {\n        var getType = {};\n        return object && getType.toString.call(object) === '[object Function]';\n    }\n\n    function noop() {}\n\n    function noargs(fn) {\n        return function() {\n            return fn();\n        };\n    }\n\n    function asynchronize(ctx, fn) {\n        return function() {\n            var next = slice.call(arguments, arguments.length - 1)[0];\n            var args = slice.call(arguments, 0, arguments.length - 2);\n            fn.apply(ctx, args);\n            if (next) next();\n        };\n    }\n\n    return {\n        noop: noop,\n        noargs: noargs,\n        async_noop: asynchronize(null, noop),\n        asynchronize: asynchronize,\n        is_function: is_function,\n        curry: curry,\n        invoke: invoke\n    };\n\n\n})();\n\n},{}],23:[function(require,module,exports){\n\"use strict\";\r\n\r\nvar Language =  require('./Language');\r\n\r\nmodule.exports = (function() {\r\n\r\n    var vocabulary = {\r\n        feature: '[Ff]eature|功能',\r\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\r\n        examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\r\n        pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\r\n        only: '(?:[Oo]nly|仅仅?)',\r\n        background: '[Bb]ackground|背景|前提',\r\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\r\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\r\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\r\n        _steps: ['given', 'when', 'then']\r\n    };\r\n\r\n    return new Language('Chinese', vocabulary);\r\n})();\r\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n        scenario: '(?:[Ss]cenario|[Gg|eval)',\n        examples: '(?:[Vv]oorbeelden?)',\n        pending: '(?:[Tt]odo|[Mm]oet nog)',\n        only: '(?:[Aa]lleen)',\n        background: '(?:[Aa]chtergrond)',\n        given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n        when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n        then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ff]eature',\n        scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n        examples: '(?:[Ee]xamples|[Ww]here)',\n        pending: '(?:[Pp]ending|[Tt]odo)',\n        only: '(?:[Oo]nly)',\n        background: '[Bb]ackground',\n        given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]onctionnalité)',\n        scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n        examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n        pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n        only: '(?:[Ss]eulement])',\n        background: '(?:[Cc]ontexte)',\n        given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n        when: '(?:[Qq]uand|[Ll]orsqu\\'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)',\n        then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'soit', 'etantdonnees', 'etantdonnee', 'etantdonne',\n            'quand', 'lorsque',\n            'alors'\n        ],\n        // Also aliasing French verbs for given-when-then for signature-lookup\n        get soit() { return this.given; },\n        get etantdonnees() { return this.given; },\n        get etantdonnee() { return this.given; },\n        get etantdonne() { return this.given; },\n        get quand() { return this.when; },\n        get lorsque() { return this.when; },\n        get alors() { return this.then; }\n    };\n\n    return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n        scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n        examples: '(?:[Bb]eispiele?)',\n        pending: '(?:[Tt]odo|[Oo]ffen)',\n        only: '(?:[Nn]ur|[Ee]inzig)',\n        background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n        given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n        when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n        then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n\"use strict\";\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function(name, vocabulary) {\n\n    var _this = this;\n\n    // See http://github.com/acuminous/yadda#203\n    this.is_language = true;\n\n    this.library = function(dictionary) {\n        return _this.localise_library(new Library(dictionary));\n    };\n\n    this.localise_library = function(library) {\n        $(vocabulary._steps).each(function(keyword) {\n            library[keyword] = function(signatures, fn, ctx, options) {\n                return $(signatures).each(function(signature) {\n                    signature = prefix_signature(_this.localise(keyword), signature);\n                    return library.define(signature, fn, ctx, options);\n                });\n            };\n        });\n        return library;\n    };\n\n    var prefix_signature = function(prefix, signature) {\n        var regex_delimiters = new RegExp('^/|/$', 'g');\n        var start_of_signature = new RegExp(/^(?:\\^)?/);\n        var one_or_more_spaces = '\\\\s+';\n        var leading_spaces = '^(?:\\\\s)*';\n        return signature.toString().replace(regex_delimiters, '').replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n    };\n\n    this.localise = function(keyword) {\n        if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n        return vocabulary[keyword];\n    };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '[Ee]genskap',\n        scenario: '[Ss]cenario',\n        examples: '[Ee]ksempler',\n        pending: '[Aa]vventer',\n        only: '[Bb]are',\n        background: '[Bb]akgrunn',\n        given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n        when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n        then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n        _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n        // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n        get gitt() { return this.given; },\n        get når() { return this.when; },\n        get så() { return this.then; }\n    };\n\n    return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Tt]ale|[Yy]arn)',\n        scenario: '(?:[Aa]dventure|[Ss]ortie)',\n        examples: '[Ww]herest',\n        pending: '[Bb]rig',\n        only: '[Bb]lack [Ss]pot',\n        background: '[Aa]ftground',\n        given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n        when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n        then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n        _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n        // Also aliasing Pirate verbs for given-when-then for signature-lookup\n        get giveth() { return this.given; },\n        get whence() { return this.when; },\n        get thence() { return this.then; }\n\n    };\n\n    return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n        scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n        examples: '[Pp]rzykłady',\n        pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n        only: '[Tt]ylko',\n        background: '[Zz]ałożenia',\n        given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n        when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n        then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n        _steps: [\n            'given', 'when', 'then',\n            'zakladajac', 'majac',\n            'jezeli', 'jesli', 'gdy', 'kiedy',\n            'wtedy'\n        ],\n        // Also aliasing Polish verbs for given-when-then for signature-lookup\n        get zakladajac() { return this.given; },\n        get majac() { return this.given; },\n        get jezeli() { return this.when; },\n        get jesli() { return this.when; },\n        get gdy() { return this.when; },\n        get kiedy() { return this.when; },\n        get wtedy() { return this.then; }\n    };\n\n    return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n        scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n        examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n        pending: '[Pp]endente',\n        only: '[S][óo]',\n        background: '[Ff]undo',\n        given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n        when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n        then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas',\n            'quando', 'se',\n            'entao'\n        ],\n\n        get seja() { return this.given; },\n        get sejam() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get quando() { return this.when; },\n        get se() { return this.when; },\n        get entao() { return this.then; }\n    };\n\n    return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n        scenario: 'Сценарий',\n        examples: 'Примеры?',\n        pending: '(?:[Ww]ip|[Tt]odo)',\n        only: 'Только',\n        background: '(?:[Пп]редыстория|[Кк]онтекст)',\n        given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n        scenario: '(?:[Ee]scenario|[Cc]aso)',\n        examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n        pending: '[Pp]endiente',\n        only: '[S]ólo',\n        background: '[Ff]ondo',\n        given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n        when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n        then: '(?:[Ee]ntonces)',\n\n        _steps: [\n            'given', 'when', 'then',\n            'sea', 'sean', 'dado', 'dada','dados', 'dadas',\n            'cuando', 'si',\n            'entonces'\n        ],\n\n        get sea() { return this.given; },\n        get sean() { return this.given; },\n        get dado() { return this.given; },\n        get dada() { return this.given; },\n        get dados() { return this.given; },\n        get dadas() { return this.given; },\n        get cuando() { return this.when; },\n        get si() { return this.when; },\n        get entonces() { return this.then; }\n    };\n\n    return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n\"use strict\";\n\nvar Language = require('./Language');\n\nmodule.exports = (function() {\n\n    var vocabulary = {\n        feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n        scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n        examples: '[Пп]риклади',\n        pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n        only: '[Тт]ільки',\n        background: '[Кк]онтекст',\n        given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n        when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n        then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n        _steps: ['given', 'when', 'then']\n    };\n\n    return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    Chinese: require('./Chinese'),\n    English: require('./English'),\n    French: require('./French'),\n    German: require('./German'),\n    Dutch: require('./Dutch'),\n    Norwegian: require('./Norwegian'),\n    Pirate: require('./Pirate'),\n    Ukrainian: require('./Ukrainian'),\n    Polish: require('./Polish'),\n    Spanish: require('./Spanish'),\n    Russian: require('./Russian'),\n    Portuguese: require('./Portuguese'),\n    default: require('./English'),\n    Language: require('./Language')\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n\"use strict\";\n\nvar FeatureFileParser = function(options) {\n\n    var fs = require('../shims').fs;\n    var FeatureParser = require('./FeatureParser');\n    var parser = new FeatureParser(options);\n\n    this.parse = function(file, next) {\n        var text = fs.readFileSync(file, 'utf8');\n        var feature = parser.parse(text);\n        return next && next(feature) || feature;\n    };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function(options) {\n\n    /* eslint-disable no-redeclare */\n    var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']'};\n    var options = options && options.is_language ? { language: options } : options || defaults;\n    var language = options.language || defaults.language;\n    var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n    var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n    /* eslint-enable no-redeclare */\n\n    var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n    var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n    var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n    var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n    var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n    var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n    var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n    var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n    var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n    var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n    var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n    var specification;\n    var comment;\n\n    this.parse = function(text, next) {\n        reset();\n        split(text).each(parse_line);\n        return next && next(specification.export()) || specification.export();\n    };\n\n    function reset() {\n        specification = new Specification();\n        comment = false;\n    }\n\n    function split(text) {\n        return $(text.split(/\\r\\n|\\n/));\n    }\n\n    function parse_line(line, index) {\n        var match;\n        var line_number = index + 1;\n        try {\n            // eslint-disable-next-line no-return-assign\n            if (match = MULTI_LINE_COMMENT_REGEX.test(line)) return comment = !comment;\n            if (comment) return;\n            if (match = SINGLE_LINE_COMMENT_REGEX.test(line)) return;\n            if (match = SIMPLE_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n            if (match = NVP_ANNOTATION_REGEX.exec(line)) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n            if (match = FEATURE_REGEX.exec(line)) return specification.handle('Feature', match[1], line_number);\n            if (match = SCENARIO_REGEX.exec(line)) return specification.handle('Scenario', match[1], line_number);\n            if (match = BACKGROUND_REGEX.exec(line)) return specification.handle('Background', match[1], line_number);\n            if (match = EXAMPLES_REGEX.exec(line)) return specification.handle('Examples', line_number);\n            if (match = BLANK_REGEX.exec(line)) return specification.handle('Blank', match[0], line_number);\n            if (match = DASH_REGEX.exec(line)) return specification.handle('Dash', match[1], line_number);\n            if (match = TEXT_REGEX.exec(line)) return specification.handle('Text', match[1], line_number);\n        } catch (e) {\n            e.message = 'Error parsing line ' + (line_number) + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n            throw e;\n        }\n    }\n\n    var Handlers = function(handlers) {\n\n        // eslint-disable-next-line no-redeclare\n        var handlers = handlers || {};\n\n        this.register = function(event, handler) {\n            handlers[event] = handler;\n        };\n\n        this.unregister = function() {\n            $(Array.prototype.slice.call(arguments)).each(function(event) {\n                delete handlers[event];\n            });\n        };\n\n        this.find = function(event) {\n            if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n            return { handle: handlers[event.toLowerCase()] };\n        };\n    };\n\n    var Specification = function() {\n\n        var current_element = this;\n        var feature;\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            text: fn.noop,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            feature: start_feature,\n            scenario: start_scenario,\n            background: start_background\n        });\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function start_feature(event, title) {\n            // eslint-disable-next-line no-return-assign\n            return feature = new Feature(title, annotations, new Annotations());\n        }\n\n        function start_scenario(event, title, line_number) {\n            feature = new Feature(title, new Annotations(), annotations);\n            return feature.on(event, title, line_number);\n        }\n\n        var start_background = start_scenario;\n\n        this.handle = function(event, data, line_number) {\n            current_element = current_element.on(event, data, line_number);\n        };\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            if (!feature) throw new Error('A feature must contain one or more scenarios');\n            return feature.export();\n        };\n    };\n\n    var Annotations = function() {\n\n        var annotations = {};\n\n        this.stash = function(key, value) {\n            if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n            annotations[key.toLowerCase()] = value;\n        };\n\n        this.export = function() {\n            return annotations;\n        };\n    };\n\n    var Feature = function(title, annotations, stashed_annotations) {\n\n        var description = [];\n        var scenarios = [];\n        var background = new NullBackground();\n        var handlers = new Handlers({\n            text: capture_description,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario,\n            background: start_background\n        });\n        var _this = this;\n\n        function start_background(event, title) {\n            background = new Background(title, _this);\n            stashed_annotations = new Annotations();\n            return background;\n        }\n\n        function stash_annotation(event, annotation) {\n            handlers.unregister('background', 'text');\n            stashed_annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_description(event, text) {\n            description.push(StringUtils.trim(text));\n        }\n\n        function start_scenario(event, title) {\n            var scenario = new Scenario(title, background, stashed_annotations, _this);\n            scenarios.push(scenario);\n            stashed_annotations = new Annotations();\n            return scenario;\n        }\n\n        function validate() {\n            if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                scenarios: $(scenarios).collect(function(scenario) {\n                    return scenario.export();\n                }).flatten().naked()\n            };\n        };\n    };\n\n    var Background = function(title, feature) {\n\n        var steps = [];\n        var blanks = [];\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: stash_annotation,\n            scenario: start_scenario\n        });\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', stash_annotation);\n            handlers.register('scenario', start_scenario);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            validate();\n            return feature.on(event, annotation, line_number);\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Background requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            return {\n                steps: steps\n            };\n        };\n    };\n\n    var NullBackground = function() {\n        var handlers = new Handlers();\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            return {\n                steps: []\n            };\n        };\n    };\n\n    var Scenario = function(title, background, annotations, feature) {\n        var description = [];\n        var steps = [];\n        var blanks = [];\n        var examples;\n        var indentation = 0;\n        var handlers = new Handlers({\n            text: capture_step,\n            blank: fn.noop,\n            annotation: start_scenario,\n            scenario: start_scenario,\n            examples: start_examples\n        });\n        var _this = this;\n\n        function capture_step(event, text, line_number) {\n            handlers.register('dash', enable_multiline_step);\n            steps.push(StringUtils.trim(text));\n        }\n\n        function enable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n            handlers.register('text', start_multiline_step);\n            handlers.register('blank', stash_blanks);\n            indentation = StringUtils.indentation(text);\n        }\n\n        function start_multiline_step(event, text, line_number) {\n            handlers.register('dash', disable_multiline_step);\n            handlers.register('text', continue_multiline_step);\n            handlers.register('blank', stash_blanks);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n            handlers.register('examples', start_examples);\n            append_to_step(text, '\\n');\n        }\n\n        function continue_multiline_step(event, text, line_number) {\n            unstash_blanks();\n            append_to_step(text, '\\n');\n        }\n\n        function stash_blanks(event, text, line_number) {\n            blanks.push(text);\n        }\n\n        function unstash_blanks() {\n            if (!blanks.length) return;\n            append_to_step(blanks.join('\\n'), '\\n');\n            blanks = [];\n        }\n\n        function disable_multiline_step(event, text, line_number) {\n            handlers.unregister('dash');\n            handlers.register('text', capture_step);\n            handlers.register('blank', fn.noop);\n            unstash_blanks();\n        }\n\n        function append_to_step(text, prefix) {\n            if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n            steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return feature.on(event, data, line_number);\n        }\n\n        function start_examples(event, data, line_number) {\n            validate();\n            examples = new Examples(_this);\n            return examples;\n        }\n\n        function validate() {\n            if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.export = function() {\n            validate();\n            var result = {\n                title: title,\n                annotations: annotations.export(),\n                description: description,\n                steps: background.export().steps.concat(steps)\n            };\n            return examples ? examples.expand(result) : result;\n        };\n    };\n\n    var Examples = function(scenario) {\n\n        var headings = [];\n        var examples = $();\n        var annotations = new Annotations();\n        var handlers = new Handlers({\n            blank: fn.noop,\n            dash: start_example_table,\n            text: capture_headings\n        });\n\n        function start_example_table(evnet, data, line_number) {\n            handlers.unregister('blank', 'dash');\n        }\n\n        function capture_headings(event, data, line_number) {\n            handlers.register('annotation', stash_annotation);\n            handlers.register('text', capture_singleline_fields);\n            handlers.register('dash', enable_multiline_examples);\n            var pos = 1;\n            headings = split(data).collect(function(column) {\n                var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n                pos += column.length + 1;\n                return attributes;\n            }).naked();\n        }\n\n        function stash_annotation(event, annotation, line_number) {\n            handlers.unregister('blank', 'dash');\n            annotations.stash(annotation.key, annotation.value);\n        }\n\n        function capture_singleline_fields(event, data, line_number) {\n            handlers.register('dash', end_example_table);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n            annotations = new Annotations();\n        }\n\n        function enable_multiline_examples(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n        }\n\n        function start_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', continue_capturing_multiline_fields);\n            handlers.register('dash', stop_capturing_multiline_fields);\n            handlers.register('blank', end_example_table);\n            examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n            add_meta_fields(line_number);\n        }\n\n        function continue_capturing_multiline_fields(event, data, line_number) {\n            parse_fields(data, examples.last().fields);\n        }\n\n        function stop_capturing_multiline_fields(event, data, line_number) {\n            handlers.register('text', start_capturing_multiline_fields);\n            annotations = new Annotations();\n        }\n\n        function end_example_table(event, data, line_number) {\n            handlers.unregister('text', 'dash');\n            handlers.register('blank', fn.noop);\n            handlers.register('annotation', start_scenario);\n            handlers.register('scenario', start_scenario);\n        }\n\n        function add_meta_fields(line_number) {\n            var fields = examples.last().fields;\n            $(headings).each(function(heading) {\n                fields[heading.text + '.index'] = [ examples.length ];\n                fields[heading.text + '.start.line'] = [ line_number ];\n                fields[heading.text + '.start.column'] = [ heading.left + heading.indentation ];\n            });\n        }\n\n        function parse_fields(row, fields) {\n            split(row, headings.length).each(function(field, index) {\n                var column = headings[index].text;\n                var indentation = headings[index].indentation;\n                var text = StringUtils.rtrim(field.substr(indentation));\n                if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n                fields[column] = (fields[column] || []).concat(text);\n            });\n            return fields;\n        }\n\n        function split(row, number_of_fields) {\n            var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n            var fields = $(row.split(separator));\n            if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n                throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n            }\n            return fields;\n        }\n\n        function start_scenario(event, data, line_number) {\n            validate();\n            return scenario.on(event, data, line_number);\n        }\n\n        function validate() {\n            if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n            if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n        }\n\n        this.on = function(event, data, line_number) {\n            return handlers.find(event).handle(event, data, line_number) || this;\n        };\n\n        this.expand = function(scenario) {\n            validate();\n            return examples.collect(function(example) {\n                return {\n                    title: substitute(example.fields, scenario.title),\n                    annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n                    description: substitute_all(example, scenario.description),\n                    steps: substitute_all(example.fields, scenario.steps)\n                };\n            }).naked();\n        };\n\n        function shallow_merge() {\n            var result = {};\n            $(Array.prototype.slice.call(arguments)).each(function(annotations) {\n                for (var key in annotations) {\n                    result[key] = annotations[key];\n                }\n            });\n            return result;\n        }\n\n        function substitute_all(example, lines) {\n            return $(lines).collect(function(line) {\n                return substitute(example, line);\n            }).naked();\n        }\n\n        function substitute(example, line) {\n            for (var heading in example) {\n                line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n            }\n            return line;\n        }\n    };\n\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar StepParser = function() {\n\n    var NON_BLANK_REGEX = /[^\\s]/;\n\n    this.parse = function(text, next) {\n        var steps = split(text).find_all(non_blanks);\n        return next && next(steps) || steps;\n    };\n\n    var split = function(text) {\n        return $(text.split(/\\n/));\n    };\n\n    var non_blanks = function(text) {\n        return text && NON_BLANK_REGEX.test(text);\n    };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    StepParser: require('./StepParser'),\n    FeatureParser: require('./FeatureParser'),\n    FeatureFileParser: require('./FeatureFileParser')\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){(function (){\n\"use strict\";\n\nif (!module.client) {\n    var fs = require(\"../shims\").fs;\n    global.process = global.process || {\n        cwd: function() {\n            return fs.workingDirectory;\n        }\n    };\n}\n\n\nmodule.exports = function(yadda, casper) {\n\n    var EventBus = require('yadda').EventBus;\n\n    yadda.interpreter.interpret_step = function(step, ctx, next) {\n\n        var _this = this;\n        casper.then(function() {\n            casper.test.info(step);\n            EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n            _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n        });\n    };\n\n    casper.yadda = function(script, ctx) {\n        if (script === undefined) return this;\n        yadda.run(script, ctx);\n    };\n};\n\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = {\n    casper: require('./CasperPlugin'),\n    mocha: {\n        ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n        StepLevelPlugin: require('./mocha/StepLevelPlugin')\n    },\n    get jasmine() {\n        return this.mocha;\n    }\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n\"use strict\";\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function(options) {\n\n    /* jslint shadow: true */\n    var platform = new Platform();\n    var language = options.language || Localisation.default;\n    var parser = options.parser || new FeatureFileParser(language);\n    var container = options.container || platform.get_container();\n\n    function featureFiles(files, iterator) {\n        $(files).each(function(file) {\n            features(parser.parse(file), iterator);\n        });\n    }\n\n    function features(features, iterator) {\n        $(features).each(function(feature) {\n            describe(feature.title, feature, iterator);\n        });\n    }\n\n    function describe(title, subject, iterator) {\n        var _describe = getDescribe(subject.annotations);\n        _describe(title, function() {\n            iterator(subject);\n        });\n    }\n\n    function it_async(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function(done) {\n            iterator(this, subject, done);\n        });\n    }\n\n    function it_sync(title, subject, iterator) {\n        var _it = getIt(subject.annotations);\n        _it(title, function() {\n            iterator(this, subject);\n        });\n    }\n\n    function getIt(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xit;\n        if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n        return container.it;\n    }\n\n    function getDescribe(annotations, next) {\n        if (has_annotation(annotations, 'pending')) return container.xdescribe;\n        if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n        return container.describe;\n    }\n\n    function has_annotation(annotations, name) {\n        var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n        for (var key in annotations) {\n            if (regexp.test(key)) return true;\n        }\n    }\n\n    return {\n        featureFiles: featureFiles,\n        features: features,\n        describe: describe,\n        it_async: it_async,\n        it_sync: it_sync\n    };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n            itFn(scenario.title, scenario, function(context, scenario, done) {\n                iterator(scenario, done);\n            });\n        });\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function(options) {\n\n    // eslint-disable-next-line no-redeclare\n    var options = options || {};\n    var platform = new Platform();\n    var container = options.container || platform.get_container();\n\n    var base_plugin = BasePlugin.create(options);\n\n    function scenarios(scenarios, iterator) {\n        $(scenarios).each(function(scenario) {\n            base_plugin.describe(scenario.title, scenario, iterator);\n        });\n    }\n\n    function steps(steps, iterator) {\n\n        var abort = false;\n\n        $(steps).each(function(step) {\n            var stepFn = iterator.length === 1 ? step_sync : step_async;\n            stepFn(step, iterator);\n        });\n\n        function step_async(step, iterator) {\n            base_plugin.it_async(step, step, function(context, step, done) {\n                if (abort) {\n                    return context.skip ? context.skip() : done();\n                }\n                abort = true;\n                iterator.bind(context)(step, function(err) {\n                    if (err) return (done.fail || done)(err);\n                    abort = false;\n                    done();\n                });\n            });\n        }\n\n        function step_sync(step, iterator) {\n            base_plugin.it_sync(step, step, function(context, step) {\n                if (abort) return context.skip && context.skip();\n                abort = true;\n                iterator.bind(context)(step);\n                abort = false;\n            });\n        }\n    }\n\n    container.featureFiles = container.featureFile = base_plugin.featureFiles;\n    container.features = container.feature = base_plugin.features;\n    container.scenarios = container.scenario = scenarios;\n    container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n\"use strict\";\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function(s1, s2) {\n\n    this.value;\n    this.type = 'LevenshteinDistanceScore';\n    var distance_table;\n    var _this = this;\n\n    var initialise = function() {\n\n        var x = s1.length;\n        var y = s2.length;\n\n        distance_table = new Array(x + 1);\n\n        /* eslint-disable no-redeclare */\n        for (var i = 0; i <= x; i++) {\n            distance_table[i] = new Array(y + 1);\n        }\n\n        for (var i = 0; i <= x; i++) {\n            for (var j = 0; j <= y; j++) {\n                distance_table[i][j] = 0;\n            }\n        }\n\n        for (var i = 0; i <= x; i++) {\n            distance_table[i][0] = i;\n        }\n\n        for (var j = 0; j <= y; j++) {\n            distance_table[0][j] = j;\n        }\n        /* eslint-enable no-redeclare */\n    };\n\n    var score = function() {\n\n        // eslint-disable-next-line no-return-assign\n        if (s1 === s2) return _this.value = 0;\n\n        for (var j = 0; j < s2.length; j++) {\n            for (var i = 0; i < s1.length; i++) {\n                if (s1[i] === s2[j]) {\n                    distance_table[i+1][j+1] = distance_table[i][j];\n                } else {\n                    var deletion = distance_table[i][j+1] + 1;\n                    var insertion = distance_table[i+1][j] + 1;\n                    var substitution = distance_table[i][j] + 1;\n                    distance_table[i+1][j+1] = Math.min(substitution, deletion, insertion);\n                }\n            }\n        }\n        _this.value = distance_table[s1.length][s2.length];\n    };\n\n    this.compare = function(other) {\n        return other.value - this.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n\n    initialise();\n    score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n\"use strict\";\n\nvar $ = require('../Array');\n\nvar MultiScore = function(scores) {\n\n    this.scores = $(scores);\n    this.type = 'MultiScore';\n\n    this.compare = function(other) {\n        for (var i = 0; i < this.scores.length; i++) {\n            var difference = this.scores[i].compare(other.scores[i]);\n            if (difference) return difference;\n        }\n        return 0;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        if (this.type !== other.type) return false;\n        return this.compare(other) === 0;\n    };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n\"use strict\";\n\nvar SameLibraryScore = function(m1, m2) {\n\n    this.value = m1.is_sibling(m2) ? 1 : 0;\n    this.type = 'SameLibraryScore';\n\n    this.compare = function(other) {\n        return this.value - other.value;\n    };\n\n    this.equals = function(other) {\n        if (!other) return false;\n        return (this.type === other.type && this.value === other.value);\n    };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){(function (){\n\"use strict\";\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n\n    var platform = new Platform();\n\n    var shims = {\n        node: function () {\n            return {\n                fs: require('fs'),\n                path: require('path'),\n                process: process\n            };\n        },\n        phantom: function () {\n            return {\n                fs: require('./phantom-fs'),\n                path: require('./phantom-path'),\n                process: require('./phantom-process')\n            };\n        },\n        karma: function () {\n            return {\n                fs: require('./karma-fs'),\n                path: require('./karma-path'),\n                process: require('./karma-process')\n            };\n        }\n    };\n\n    function get_shim() {\n        if (platform.is_phantom()) return shims.phantom();\n        if (platform.is_browser() && platform.is_karma()) return shims.karma();\n        if (platform.is_node()) return shims.node();\n        return {};\n    }\n\n    return get_shim();\n})();\n\n}).call(this)}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\n\nmodule.exports = (function() {\n    \"use strict\";\n\n    var path = require(\"./karma-path\");\n\n    function absolutePath(relativePath) {\n        return path.resolve(path.normalize(relativePath.split(\"\\\\\").join(\"/\")));\n    }\n\n    var KarmaFileSystem = function() {\n        this.registry = new KarmaPathRegistry();\n        this.converter = new KarmaUriPathConverter(\"/base/\", \"/\");\n        this.reader = new KarmaFileReader(this.converter);\n\n        var servedUris = Object.keys(window.__karma__.files);\n        var servedFiles = this.converter.parseUris(servedUris);\n        servedFiles.forEach(this.registry.addFile, this.registry);\n    };\n    KarmaFileSystem.prototype = {\n        constructor: KarmaFileSystem,\n        workingDirectory: \"/\",\n        existsSync: function(path) {\n            return this.registry.exists(path);\n        },\n        readdirSync: function(path) {\n            return this.registry.getContent(path);\n        },\n        statSync: function(path) {\n            return {\n                isDirectory: function() {\n                    return this.registry.isDirectory(path);\n                }.bind(this)\n            };\n        },\n        readFileSync: function(file, encoding) {\n            if (encoding !== \"utf8\") throw new Error(\"This fs.readFileSync() shim does not support other than utf8 encoding.\");\n            if (!this.registry.isFile(file)) throw new Error(\"File does not exist: \" + file);\n            return this.reader.readFile(file);\n        }\n    };\n\n    var KarmaPathRegistry = function KarmaPathRegistry() {\n        this.paths = {};\n    };\n\n    KarmaPathRegistry.prototype = {\n        constructor: KarmaPathRegistry,\n        addFile: function(file) {\n            file = absolutePath(file);\n            this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n            var parentDirectory = path.dirname(file);\n            this.addDirectory(parentDirectory);\n        },\n        addDirectory: function(directory) {\n            directory = absolutePath(directory);\n            this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n            var parentDirectory = path.dirname(directory);\n            if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n        },\n        isFile: function(file) {\n            file = absolutePath(file);\n            return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n        },\n        isDirectory: function(directory) {\n            directory = absolutePath(directory);\n            return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n        },\n        exists: function(node) {\n            node = absolutePath(node);\n            return this.paths.hasOwnProperty(node);\n        },\n        getContent: function(directory) {\n            if (!this.isDirectory(directory)) throw new Error(\"Not a directory: \" + directory);\n            directory = absolutePath(directory);\n            return Object.keys(this.paths).filter(function(node) {\n                if (node === directory) return false;\n                var parentDirectory = path.dirname(node);\n                return parentDirectory === directory;\n            }, this).map(function(node) {\n                return path.basename(node);\n            });\n        }\n    };\n\n    KarmaPathRegistry.TYPE_FILE = 0;\n    KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n    var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n        this.workingDirectory = workingDirectory;\n        this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n        this.baseUri = baseUri;\n        this.baseUriPattern = this.patternFromBase(baseUri);\n    };\n\n    KarmaUriPathConverter.prototype = {\n        constructor: KarmaUriPathConverter,\n        patternFromBase: function(string, flags) {\n            var pattern = \"^\" + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n            return new RegExp(pattern, flags);\n        },\n        parseUris: function(uris) {\n            return uris.filter(function(uri) {\n                return this.baseUriPattern.test(uri);\n            }, this).map(function(uri) {\n                return uri.replace(this.baseUriPattern, this.workingDirectory);\n            }, this);\n        },\n        buildUri: function(file) {\n            file = absolutePath(file);\n            if (!this.workingDirectoryPattern.test(file)) throw new Error(\"Path is not in working directory: \" + file);\n            return file.replace(this.workingDirectoryPattern, this.baseUri);\n        }\n    };\n\n    var KarmaFileReader = function KarmaFileReader(converter) {\n        this.converter = converter;\n    };\n\n    KarmaFileReader.prototype = {\n        constructor: KarmaFileReader,\n        readFile: function(file) {\n            var uri = this.converter.buildUri(file);\n            // eslint-disable-next-line no-undef\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"get\", uri, false);\n            xhr.send();\n            return xhr.responseText;\n        }\n    };\n\n    return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\n\nmodule.exports = (function () {\n\n    \"use strict\";\n\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n    }\n\n    if (typeof path.normalize !== \"function\" || typeof path.dirname !== \"function\")\n        throw new Error(\"The path module emulation does not contain implementations of required functions.\");\n\n    return path;\n\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\n\nmodule.exports = (function() {\n\n    \"use strict\";\n\n    var fs = require(\"./karma-fs\");\n    var process = {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n\n    fs.existsSync = fs.existsSync || fs.exists;\n\n    fs.readdirSync = fs.readdirSync || function(path) {\n        return fs.list(path).filter(function(name) {\n            return name !== '.' && name !== '..';\n        });\n    };\n\n    fs.statSync = fs.statSync || function(path) {\n        return {\n            isDirectory: function() {\n                return fs.isDirectory(path);\n            }\n        };\n    };\n\n    return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var path = {};\n\n    try {\n        path = require('path');\n    } catch (e) {\n        // meh\n    }\n\n    path.join = path.join || function() {\n        return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n    path.relative = path.relative || function(from, to) {\n        return from + fs.separator + to;\n    };\n\n    return path;\n\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n\"use strict\";\n\nmodule.exports = (function() {\n    if (module.client) return {}; // Running in browser, not via node\n\n    var fs = require('fs');\n    var process = typeof process !== 'undefined' ? process : {};\n\n    process.cwd = function() {\n        return fs.workingDirectory;\n    };\n\n    return process;\n\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){(function (){\n// 'path' module extracted from Node.js v8.11.1 (only the posix part)\n// transplited with Babel\n\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nfunction assertPath(path) {\n  if (typeof path !== 'string') {\n    throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));\n  }\n}\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeStringPosix(path, allowAboveRoot) {\n  var res = '';\n  var lastSegmentLength = 0;\n  var lastSlash = -1;\n  var dots = 0;\n  var code;\n  for (var i = 0; i <= path.length; ++i) {\n    if (i < path.length)\n      code = path.charCodeAt(i);\n    else if (code === 47 /*/*/)\n      break;\n    else\n      code = 47 /*/*/;\n    if (code === 47 /*/*/) {\n      if (lastSlash === i - 1 || dots === 1) {\n        // NOOP\n      } else if (lastSlash !== i - 1 && dots === 2) {\n        if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {\n          if (res.length > 2) {\n            var lastSlashIndex = res.lastIndexOf('/');\n            if (lastSlashIndex !== res.length - 1) {\n              if (lastSlashIndex === -1) {\n                res = '';\n                lastSegmentLength = 0;\n              } else {\n                res = res.slice(0, lastSlashIndex);\n                lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n              }\n              lastSlash = i;\n              dots = 0;\n              continue;\n            }\n          } else if (res.length === 2 || res.length === 1) {\n            res = '';\n            lastSegmentLength = 0;\n            lastSlash = i;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          if (res.length > 0)\n            res += '/..';\n          else\n            res = '..';\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0)\n          res += '/' + path.slice(lastSlash + 1, i);\n        else\n          res = path.slice(lastSlash + 1, i);\n        lastSegmentLength = i - lastSlash - 1;\n      }\n      lastSlash = i;\n      dots = 0;\n    } else if (code === 46 /*.*/ && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\n\nfunction _format(sep, pathObject) {\n  var dir = pathObject.dir || pathObject.root;\n  var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');\n  if (!dir) {\n    return base;\n  }\n  if (dir === pathObject.root) {\n    return dir + base;\n  }\n  return dir + sep + base;\n}\n\nvar posix = {\n  // path.resolve([from ...], to)\n  resolve: function resolve() {\n    var resolvedPath = '';\n    var resolvedAbsolute = false;\n    var cwd;\n\n    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n      var path;\n      if (i >= 0)\n        path = arguments[i];\n      else {\n        if (cwd === undefined)\n          cwd = process.cwd();\n        path = cwd;\n      }\n\n      assertPath(path);\n\n      // Skip empty entries\n      if (path.length === 0) {\n        continue;\n      }\n\n      resolvedPath = path + '/' + resolvedPath;\n      resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    }\n\n    // At this point the path should be resolved to a full absolute path, but\n    // handle relative paths to be safe (might happen when process.cwd() fails)\n\n    // Normalize the path\n    resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);\n\n    if (resolvedAbsolute) {\n      if (resolvedPath.length > 0)\n        return '/' + resolvedPath;\n      else\n        return '/';\n    } else if (resolvedPath.length > 0) {\n      return resolvedPath;\n    } else {\n      return '.';\n    }\n  },\n\n  normalize: function normalize(path) {\n    assertPath(path);\n\n    if (path.length === 0) return '.';\n\n    var isAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;\n\n    // Normalize the path\n    path = normalizeStringPosix(path, !isAbsolute);\n\n    if (path.length === 0 && !isAbsolute) path = '.';\n    if (path.length > 0 && trailingSeparator) path += '/';\n\n    if (isAbsolute) return '/' + path;\n    return path;\n  },\n\n  isAbsolute: function isAbsolute(path) {\n    assertPath(path);\n    return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;\n  },\n\n  join: function join() {\n    if (arguments.length === 0)\n      return '.';\n    var joined;\n    for (var i = 0; i < arguments.length; ++i) {\n      var arg = arguments[i];\n      assertPath(arg);\n      if (arg.length > 0) {\n        if (joined === undefined)\n          joined = arg;\n        else\n          joined += '/' + arg;\n      }\n    }\n    if (joined === undefined)\n      return '.';\n    return posix.normalize(joined);\n  },\n\n  relative: function relative(from, to) {\n    assertPath(from);\n    assertPath(to);\n\n    if (from === to) return '';\n\n    from = posix.resolve(from);\n    to = posix.resolve(to);\n\n    if (from === to) return '';\n\n    // Trim any leading backslashes\n    var fromStart = 1;\n    for (; fromStart < from.length; ++fromStart) {\n      if (from.charCodeAt(fromStart) !== 47 /*/*/)\n        break;\n    }\n    var fromEnd = from.length;\n    var fromLen = fromEnd - fromStart;\n\n    // Trim any leading backslashes\n    var toStart = 1;\n    for (; toStart < to.length; ++toStart) {\n      if (to.charCodeAt(toStart) !== 47 /*/*/)\n        break;\n    }\n    var toEnd = to.length;\n    var toLen = toEnd - toStart;\n\n    // Compare paths to find the longest common path from root\n    var length = fromLen < toLen ? fromLen : toLen;\n    var lastCommonSep = -1;\n    var i = 0;\n    for (; i <= length; ++i) {\n      if (i === length) {\n        if (toLen > length) {\n          if (to.charCodeAt(toStart + i) === 47 /*/*/) {\n            // We get here if `from` is the exact base path for `to`.\n            // For example: from='/foo/bar'; to='/foo/bar/baz'\n            return to.slice(toStart + i + 1);\n          } else if (i === 0) {\n            // We get here if `from` is the root\n            // For example: from='/'; to='/foo'\n            return to.slice(toStart + i);\n          }\n        } else if (fromLen > length) {\n          if (from.charCodeAt(fromStart + i) === 47 /*/*/) {\n            // We get here if `to` is the exact base path for `from`.\n            // For example: from='/foo/bar/baz'; to='/foo/bar'\n            lastCommonSep = i;\n          } else if (i === 0) {\n            // We get here if `to` is the root.\n            // For example: from='/foo'; to='/'\n            lastCommonSep = 0;\n          }\n        }\n        break;\n      }\n      var fromCode = from.charCodeAt(fromStart + i);\n      var toCode = to.charCodeAt(toStart + i);\n      if (fromCode !== toCode)\n        break;\n      else if (fromCode === 47 /*/*/)\n        lastCommonSep = i;\n    }\n\n    var out = '';\n    // Generate the relative path based on the path difference between `to`\n    // and `from`\n    for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n      if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {\n        if (out.length === 0)\n          out += '..';\n        else\n          out += '/..';\n      }\n    }\n\n    // Lastly, append the rest of the destination (`to`) path that comes after\n    // the common path parts\n    if (out.length > 0)\n      return out + to.slice(toStart + lastCommonSep);\n    else {\n      toStart += lastCommonSep;\n      if (to.charCodeAt(toStart) === 47 /*/*/)\n        ++toStart;\n      return to.slice(toStart);\n    }\n  },\n\n  _makeLong: function _makeLong(path) {\n    return path;\n  },\n\n  dirname: function dirname(path) {\n    assertPath(path);\n    if (path.length === 0) return '.';\n    var code = path.charCodeAt(0);\n    var hasRoot = code === 47 /*/*/;\n    var end = -1;\n    var matchedSlash = true;\n    for (var i = path.length - 1; i >= 1; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          if (!matchedSlash) {\n            end = i;\n            break;\n          }\n        } else {\n        // We saw the first non-path separator\n        matchedSlash = false;\n      }\n    }\n\n    if (end === -1) return hasRoot ? '/' : '.';\n    if (hasRoot && end === 1) return '//';\n    return path.slice(0, end);\n  },\n\n  basename: function basename(path, ext) {\n    if (ext !== undefined && typeof ext !== 'string') throw new TypeError('\"ext\" argument must be a string');\n    assertPath(path);\n\n    var start = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i;\n\n    if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n      if (ext.length === path.length && ext === path) return '';\n      var extIdx = ext.length - 1;\n      var firstNonSlashEnd = -1;\n      for (i = path.length - 1; i >= 0; --i) {\n        var code = path.charCodeAt(i);\n        if (code === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else {\n          if (firstNonSlashEnd === -1) {\n            // We saw the first non-path separator, remember this index in case\n            // we need it if the extension ends up not matching\n            matchedSlash = false;\n            firstNonSlashEnd = i + 1;\n          }\n          if (extIdx >= 0) {\n            // Try to match the explicit extension\n            if (code === ext.charCodeAt(extIdx)) {\n              if (--extIdx === -1) {\n                // We matched the extension, so mark this as the end of our path\n                // component\n                end = i;\n              }\n            } else {\n              // Extension does not match, so our result is the entire path\n              // component\n              extIdx = -1;\n              end = firstNonSlashEnd;\n            }\n          }\n        }\n      }\n\n      if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;\n      return path.slice(start, end);\n    } else {\n      for (i = path.length - 1; i >= 0; --i) {\n        if (path.charCodeAt(i) === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else if (end === -1) {\n          // We saw the first non-path separator, mark this as the end of our\n          // path component\n          matchedSlash = false;\n          end = i + 1;\n        }\n      }\n\n      if (end === -1) return '';\n      return path.slice(start, end);\n    }\n  },\n\n  extname: function extname(path) {\n    assertPath(path);\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n    for (var i = path.length - 1; i >= 0; --i) {\n      var code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1)\n            startDot = i;\n          else if (preDotState !== 1)\n            preDotState = 1;\n      } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n        // We saw a non-dot character immediately before the dot\n        preDotState === 0 ||\n        // The (right-most) trimmed path component is exactly '..'\n        preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      return '';\n    }\n    return path.slice(startDot, end);\n  },\n\n  format: function format(pathObject) {\n    if (pathObject === null || typeof pathObject !== 'object') {\n      throw new TypeError('The \"pathObject\" argument must be of type Object. Received type ' + typeof pathObject);\n    }\n    return _format('/', pathObject);\n  },\n\n  parse: function parse(path) {\n    assertPath(path);\n\n    var ret = { root: '', dir: '', base: '', ext: '', name: '' };\n    if (path.length === 0) return ret;\n    var code = path.charCodeAt(0);\n    var isAbsolute = code === 47 /*/*/;\n    var start;\n    if (isAbsolute) {\n      ret.root = '/';\n      start = 1;\n    } else {\n      start = 0;\n    }\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i = path.length - 1;\n\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n\n    // Get non-dir info\n    for (; i >= start; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;\n        } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n    // We saw a non-dot character immediately before the dot\n    preDotState === 0 ||\n    // The (right-most) trimmed path component is exactly '..'\n    preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      if (end !== -1) {\n        if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);\n      }\n    } else {\n      if (startPart === 0 && isAbsolute) {\n        ret.name = path.slice(1, startDot);\n        ret.base = path.slice(1, end);\n      } else {\n        ret.name = path.slice(startPart, startDot);\n        ret.base = path.slice(startPart, end);\n      }\n      ret.ext = path.slice(startDot, end);\n    }\n\n    if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';\n\n    return ret;\n  },\n\n  sep: '/',\n  delimiter: ':',\n  win32: null,\n  posix: null\n};\n\nposix.posix = posix;\n\nmodule.exports = posix;\n\n}).call(this)}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n\"use strict\";\n\nvar api = {\n    Yadda: require('./Yadda'),\n    EventBus: require('./EventBus'),\n    Interpreter: require('./Interpreter'),\n    Context: require('./Context'),\n    Library: require('./Library'),\n    Dictionary: require('./Dictionary'),\n    FeatureFileSearch: require('./FeatureFileSearch'),\n    FileSearch: require('./FileSearch'),\n    Platform: require('./Platform'),\n    localisation: require('./localisation/index'),\n    converters: require('./converters/index'),\n    parsers: require('./parsers/index'),\n    plugins: require('./plugins/index'),\n    shims: require('./shims/index'),\n    createInstance: function() {\n        // Not everyone shares my sense of humour re the recursive api :(\n        // See https://github.com/acuminous/yadda/issues/111\n        return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n    }\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-2.1.1.js",
    "content": "require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\n'use strict';\n\nvar fn = require('./fn');\n\nmodule.exports = function (obj) {\n  function ensure_array(obj) {\n    var array = obj ? [].concat(obj) : [];\n    array.in_array = fn.curry(array, in_array, array);\n    array.each = fn.curry(array, each, array);\n    array.each_async = fn.curry(array, each_async, array);\n    array.collect = fn.curry(array, collect, array);\n    array.collect_async = fn.curry(array, collect_async, array);\n    array.flatten = fn.curry(array, flatten, array);\n    array.inject = fn.curry(array, inject, array);\n    array.push_all = fn.curry(array, push_all, array);\n    array.fill = fn.curry(array, fill, array);\n    array.find_all = fn.curry(array, find_all, array);\n    array.find = fn.curry(array, find, array);\n    array.last = fn.curry(array, last, array);\n    array.naked = fn.curry(array, naked, array);\n    return array;\n  }\n\n  function is_array(obj) {\n    return Object.prototype.toString.call(obj) === '[object Array]';\n  }\n\n  function in_array(items, item) {\n    for (var i = 0; i < items.length; i++) {\n      if (items[i] === item) {\n        return true;\n      }\n    }\n  }\n\n  function flatten(items) {\n    if (!is_array(items)) return [items];\n    if (items.length === 0) return items;\n    var head = flatten(items[0]);\n    var tail = flatten(items.slice(1));\n    return ensure_array(head.concat(tail));\n  }\n\n  function each(items, iterator) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(items[i], i);\n    }\n    return result;\n  }\n\n  function each_async(items, iterator, callback) {\n    callback = callback || fn.noop;\n    if (!items.length) return callback();\n    var index = 0;\n    var iterate = function () {\n      iterator(items[index], index, function (err, result) {\n        if (err) return callback(err);\n        if (++index >= items.length) return callback(null, result);\n        iterate();\n      });\n    };\n    iterate();\n  }\n\n  function collect(items, iterator) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      results.push(iterator(items[i], i));\n    }\n    return results;\n  }\n\n  function collect_async(items, iterator, callback) {\n    var results = ensure_array();\n    each_async(\n      items,\n      function (item, index, each_callback) {\n        iterator(item, index, function (err) {\n          if (err) return each_callback(err);\n          results.push_all(Array.prototype.splice.call(arguments, 1));\n          each_callback();\n        });\n      },\n      function (err) {\n        if (err) return callback(err);\n        callback(null, results);\n      }\n    );\n  }\n\n  function inject(items, default_value, iterator) {\n    var result = default_value;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(result, items[i]);\n    }\n    return result;\n  }\n\n  function push_all(items, more_items) {\n    more_items = more_items ? [].concat(more_items) : [];\n    for (var i = 0; i < more_items.length; i++) {\n      items.push(more_items[i]);\n    }\n    return items;\n  }\n\n  function fill(items, item, num) {\n    for (var i = 0; i < num; i++) {\n      items.push(item);\n    }\n    return items;\n  }\n\n  function find_all(items, test) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        results.push(items[i]);\n      }\n    }\n    return results;\n  }\n\n  function find(items, test) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        result = items[i];\n        break;\n      }\n    }\n    return result;\n  }\n\n  function last(items) {\n    return items[items.length - 1];\n  }\n\n  function naked(items) {\n    return [].concat(items);\n  }\n\n  return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n'use strict';\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function (step, macros, last_macro) {\n  var results = [];\n\n  this.validate = function () {\n    if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n    if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n    return { step: step, valid: true, winner: this.winner() };\n  };\n\n  this.clear_winner = function () {\n    if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n    if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n    return this.winner();\n  };\n\n  function is_undefined() {\n    return results.length === 0;\n  }\n\n  function is_ambiguous() {\n    return results.length > 1 && results[0].score.equals(results[1].score);\n  }\n\n  this.winner = function () {\n    return results[0].macro;\n  };\n\n  function winning_patterns() {\n    return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n  }\n\n  function rank(step, macros) {\n    results = macros\n      .collect(function (macro) {\n        return {\n          macro: macro,\n          score: new MultiScore([new LevenshteinDistanceScore(step, macro.levenshtein_signature()), new SameLibraryScore(macro, last_macro)]),\n        };\n      })\n      .sort(by_ascending_score);\n  }\n\n  function by_ascending_score(a, b) {\n    return b.score.compare(a.score);\n  }\n\n  function by_winning_score(result) {\n    return result.score.equals(results[0].score);\n  }\n\n  function macro_signatures(result) {\n    return result.macro.toString();\n  }\n\n  rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n'use strict';\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function (properties) {\n  // I was previously getting some weird errors using instanceof to determine if\n  // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n  this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n  this.properties = {};\n\n  this.merge = function (other) {\n    if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n    return new Context(this.properties)._merge(other);\n  };\n\n  this._merge = function (other) {\n    for (var key in other) {\n      this.properties[key] = other[key];\n    }\n    return this;\n  };\n\n  this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function (prefix) {\n  // eslint-disable-next-line no-redeclare\n  var prefix = prefix || '$';\n  var definitions = {};\n  var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n  var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n  var _this = this;\n\n  this.define = function (term, pattern, converters) {\n    if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n    if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n    if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n    if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n    definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n    return this;\n  };\n\n  this.merge = function (other) {\n    if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n    return new Dictionary(prefix)._merge(this)._merge(other);\n  };\n\n  this._merge = function (other) {\n    other.each(function (term, definition) {\n      _this.define(term, definition.pattern);\n    });\n    return this;\n  };\n\n  this._prefix = function () {\n    return prefix;\n  };\n\n  this.each = function (callback) {\n    for (var term in definitions) {\n      callback(term, definitions[term]);\n    }\n  };\n\n  this.expand = function (signature, already_expanding) {\n    var text = normalise(signature);\n    return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) } : { pattern: text, converters: get_converters(text) };\n  };\n\n  function expand_sub_terms(text, already_expanding) {\n    return get_sub_terms(text).each(function (sub_term) {\n      if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n      var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n      text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n      return text;\n    });\n  }\n\n  function get_sub_terms(text) {\n    return term_grouping_pattern.groups(text);\n  }\n\n  function expand_sub_term(sub_term, already_expanding) {\n    var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n    return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n  }\n\n  function normalise(pattern) {\n    return pattern.toString().replace(/^\\/|\\/$/g, '');\n  }\n\n  function is_defined(term) {\n    return !!definitions[term];\n  }\n\n  function is_expandable(text) {\n    return term_grouping_pattern.test(text);\n  }\n\n  function is_compatible(converters, pattern) {\n    return count_converter_arguments(converters) === count_matching_groups(pattern);\n  }\n\n  function get_converters(text) {\n    return $(text.split(term_splitting_pattern)).inject($(), function (converters, fragment) {\n      return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment) : get_matching_group_converters(fragment));\n    });\n  }\n\n  function get_matching_group_converters(text) {\n    return $().fill(pass_through_converter, count_matching_groups(text));\n  }\n\n  function get_sub_term_converters(text) {\n    return get_sub_terms(text).inject($(), function (converters, sub_term) {\n      return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters) : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n    });\n  }\n\n  function count_matching_groups(pattern) {\n    return new RegExp(pattern + '|').exec('').length - 1;\n  }\n\n  function count_converter_arguments(converters) {\n    return $(converters).inject(0, function (sum, converter) {\n      return sum + converter.length - 1;\n    });\n  }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n  var event_handlers = $();\n\n  this.send = function (event_name, event_data, next) {\n    if (arguments.length === 1) return this.send(event_name, {});\n    if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n    notify_handlers(event_name, event_data);\n    next && next();\n    return this;\n  };\n\n  this.on = function (event_pattern, callback) {\n    event_handlers.push({ pattern: event_pattern, callback: callback });\n    return this;\n  };\n\n  var notify_handlers = function (event_name, event_data) {\n    find_handlers(event_name).each(function (callback) {\n      callback({ name: event_name, data: event_data });\n    });\n  };\n\n  var find_handlers = function (event_name) {\n    return event_handlers\n      .find_all(function (handler) {\n        return new RegExp(handler.pattern).test(event_name);\n      })\n      .collect(function (handler) {\n        return handler.callback;\n      });\n  };\n}\n\nfunction instance() {\n  return event_bus;\n}\n\nmodule.exports = {\n  instance: instance,\n  ON_SCENARIO: '__ON_SCENARIO__',\n  ON_STEP: '__ON_STEP__',\n  ON_EXECUTE: '__ON_EXECUTE__',\n  ON_DEFINE: '__ON_DEFINE__',\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n'use strict';\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function (directories) {\n  this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n'use strict';\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function (directories, patterns) {\n  // eslint-disable-next-line no-redeclare\n  var patterns = patterns || /.*/;\n\n  this.each = function (fn) {\n    this.list().forEach(fn);\n  };\n\n  this.list = function () {\n    return $(directories).inject($(), function (files, directory) {\n      return files.concat(list_files(directory).find_all(by_pattern));\n    });\n  };\n\n  var list_files = function (directory) {\n    return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n  };\n\n  var list_immediate_files = function (directory) {\n    return ls(directory).find_all(by_file);\n  };\n\n  var list_sub_directory_files = function (directory) {\n    return ls(directory)\n      .find_all(by_directory)\n      .inject($(), function (files, directory) {\n        return files.concat(list_files(directory));\n      });\n  };\n\n  var ls = function (directory) {\n    if (!fs.existsSync(directory)) return $();\n    return $(fs.readdirSync(directory)).collect(function (file) {\n      return path.join(directory, file);\n    });\n  };\n\n  var by_file = function (file) {\n    return !by_directory(file);\n  };\n\n  var by_directory = function (file) {\n    return fs.statSync(file).isDirectory();\n  };\n\n  var by_pattern = function (filename) {\n    return $(patterns).find(function (pattern) {\n      return new RegExp(pattern).test(filename);\n    });\n  };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n'use strict';\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function (libraries) {\n  // eslint-disable-next-line no-redeclare\n  var libraries = $(libraries);\n  var event_bus = EventBus.instance();\n  var last_macro;\n  var _this = this;\n\n  this.requires = function (libs) {\n    libraries.push_all(libs);\n    return this;\n  };\n\n  this.validate = function (scenario) {\n    var results = $(scenario).collect(function (step) {\n      var report = _this.rank_macros(step).validate();\n      last_macro = report.winner;\n      return report;\n    });\n    if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n  };\n\n  function by_invalid_step(result) {\n    return !result.valid;\n  }\n\n  function validation_report(result) {\n    return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n  }\n\n  this.interpret = function (scenario, scenario_context, next) {\n    scenario_context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n    var iterator = make_step_iterator(scenario_context, next);\n    $(scenario).each_async(iterator, next);\n  };\n\n  var make_step_iterator = function (scenario_context, next) {\n    var iterator = function (step, index, callback) {\n      _this.interpret_step(step, scenario_context, callback);\n    };\n    return next ? iterator : fn.asynchronize(null, iterator);\n  };\n\n  this.interpret_step = function (step, scenario_context, next) {\n    var context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n    var macro = this.rank_macros(step).clear_winner();\n    last_macro = macro;\n    macro.interpret(step, context || {}, next);\n  };\n\n  this.rank_macros = function (step) {\n    return new Competition(step, compatible_macros(step), last_macro);\n  };\n\n  var compatible_macros = function (step) {\n    return libraries.inject([], function (macros, library) {\n      return macros.concat(library.find_compatible_macros(step));\n    });\n  };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n'use strict';\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function (dictionary) {\n  // eslint-disable-next-line no-redeclare\n  var dictionary = dictionary || new Dictionary();\n  var macros = $();\n  var _this = this;\n\n  this.define = function (signatures, fn, macro_context, options) {\n    $(signatures).each(function (signature) {\n      define_macro(signature, fn, macro_context, options);\n    });\n    return this;\n  };\n\n  var define_macro = function (signature, fn, macro_context, options) {\n    if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n    macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n  };\n\n  this.get_macro = function (signature) {\n    return macros.find(function (other_macro) {\n      return other_macro.is_identified_by(signature);\n    });\n  };\n\n  this.find_compatible_macros = function (step) {\n    return macros.find_all(function (macro) {\n      return macro.can_interpret(step);\n    });\n  };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n'use strict';\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function (signature, parsed_signature, macro, macro_context, library, options) {\n  /* eslint-disable no-redeclare */\n  var signature = normalise(signature);\n  var signature_pattern = new RegularExpression(parsed_signature.pattern);\n  var macro = macro || fn.async_noop;\n  var event_bus = EventBus.instance();\n  var options = options || {};\n  /* eslint-enable no-redeclare */\n\n  this.library = library;\n\n  this.is_identified_by = function (other_signature) {\n    return signature === normalise(other_signature);\n  };\n\n  this.can_interpret = function (step) {\n    return signature_pattern.test(step);\n  };\n\n  this.interpret = function (step, scenario_context, next) {\n    var context = new Context({ step: step }).merge(macro_context).merge(scenario_context);\n    convert(signature_pattern.groups(step), function (err, args) {\n      if (err) return next(err);\n      event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n      var result;\n      try {\n        result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n      } catch (err) {\n        if (next) return next(err);\n        throw err;\n      }\n      if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n      if (is_sync(args)) return next && next();\n    });\n  };\n\n  this.is_sibling = function (other_macro) {\n    return other_macro && other_macro.defined_in(library);\n  };\n\n  this.defined_in = function (other_library) {\n    return library === other_library;\n  };\n\n  this.levenshtein_signature = function () {\n    return signature_pattern.without_expressions();\n  };\n\n  this.toString = function () {\n    return signature;\n  };\n\n  function is_promise(result) {\n    if (options.mode) return options.mode === 'promise';\n    return result && result.then;\n  }\n\n  function is_sync(args) {\n    if (options.mode) return options.mode === 'sync';\n    return macro !== fn.async_noop && macro.length !== args.length + 1;\n  }\n\n  function normalise(signature) {\n    return new RegExp(signature).toString();\n  }\n\n  function convert(args, next) {\n    var index = 0;\n    return $(parsed_signature.converters)\n      .collect(function (converter) {\n        return function (callback) {\n          converter.apply(null, args.slice(index, (index += converter.length - 1)).concat(callback));\n        };\n      })\n      .collect_async(function (converter, index, callback) {\n        converter(callback);\n      }, next);\n  }\n\n  event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){(function (){\n'use strict';\n\nmodule.exports = Platform;\n\nfunction Platform() {\n  function get_container() {\n    /* eslint-disable no-undef */\n    if (is_browser()) return window;\n    if (is_phantom()) return phantom;\n    if (is_node()) return global;\n    /* eslint-enable no-undef */\n  }\n\n  function is_node() {\n    return typeof process !== 'undefined' && typeof global !== 'undefined' && typeof __dirname !== 'undefined';\n  }\n\n  function is_browser() {\n    return typeof window !== 'undefined';\n  }\n\n  function is_phantom() {\n    return typeof phantom !== 'undefined';\n  }\n\n  function is_karma() {\n    return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n  }\n\n  return {\n    get_container: get_container,\n    is_node: is_node,\n    is_browser: is_browser,\n    is_phantom: is_phantom,\n    is_karma: is_karma,\n  };\n}\n\n}).call(this)}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function (pattern_or_regexp) {\n  var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n  var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n  var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n  var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n  var non_word_tokens_pattern = /[^\\w\\s]/g;\n  var regexp = new RegExp(pattern_or_regexp);\n\n  this.test = function (text) {\n    var result = regexp.test(text);\n    this.reset();\n    return result;\n  };\n\n  this.groups = function (text) {\n    var results = $();\n    var match = regexp.exec(text);\n    while (match) {\n      var groups = match.slice(1, match.length);\n      results.push(groups);\n      match = regexp.global && regexp.exec(text);\n    }\n    this.reset();\n    return results.flatten();\n  };\n\n  this.reset = function () {\n    regexp.lastIndex = 0;\n    return this;\n  };\n\n  this.without_expressions = function () {\n    return regexp.source.replace(groups_pattern, '$1').replace(sets_pattern, '$1').replace(repetitions_pattern, '$1').replace(regex_aliases_pattern, '$1').replace(non_word_tokens_pattern, '');\n  };\n\n  this.equals = function (other) {\n    return this.toString() === other.toString();\n  };\n\n  this.toString = function () {\n    return '/' + regexp.source + '/';\n  };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  trim: function trim(text) {\n    return text.replace(/^\\s+|\\s+$/g, '');\n  },\n  rtrim: function rtrim(text) {\n    return text.replace(/\\s+$/g, '');\n  },\n  isBlank: function isBlank(text) {\n    return /^\\s*$/g.test(text);\n  },\n  isNotBlank: function isNotBlank(text) {\n    return !this.isBlank(text);\n  },\n  indentation: function indentation(text) {\n    var match = /^(\\s*)/.exec(text);\n    return (match && match[0].length) || 0;\n  },\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n'use strict';\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function (libraries, interpreter_context) {\n  if (!(this instanceof Yadda)) {\n    return new Yadda(libraries, interpreter_context);\n  }\n\n  this.interpreter = new Interpreter(libraries);\n\n  this.requires = function (libraries) {\n    this.interpreter.requires(libraries);\n    return this;\n  };\n\n  this.yadda = function (scenario, scenario_context, next) {\n    if (arguments.length === 0) return this;\n    if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n    this.interpreter.validate(scenario);\n    this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n  };\n\n  // Not everyone shares my sense of humour re the recursive api :(\n  // See https://github.com/acuminous/yadda/issues/111\n  this.run = this.yadda;\n\n  this.toString = function () {\n    return 'Yadda 2.1.1 Copyright 2010 Stephen Cresswell';\n  };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function date_converter(value, next) {\n  var converted = Date.parse(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n  return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function float_converter(value, next) {\n  var converted = parseFloat(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n  return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  date: require('./date-converter'),\n  integer: require('./integer-converter'),\n  float: require('./float-converter'),\n  list: require('./list-converter'),\n  table: require('./table-converter'),\n  pass_through: require('./pass-through-converter'),\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function integer_converter(value, next) {\n  var converted = parseInt(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n  return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function list_converter(value, next) {\n  return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function pass_through_converter(value, next) {\n  return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\nmodule.exports = function table_converter(value, next) {\n  var rows = value.split(/\\n/);\n  var headings = parse_headings(rows.shift());\n  var handler = is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n  var table = $();\n\n  try {\n    $(rows).each(handler);\n    next(null, collapse(table));\n  } catch (err) {\n    next(err);\n  }\n\n  function handle_single_line_row(row) {\n    if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n    start_new_row();\n    parse_fields(row);\n  }\n\n  function handle_multiline_row(row) {\n    if (is_horizinal_separator(row)) return start_new_row();\n    parse_fields(row);\n  }\n\n  function parse_headings(row) {\n    return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX))\n      .collect(function (value) {\n        return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n      })\n      .naked();\n  }\n\n  function is_horizinal_separator(row) {\n    return DASH_REGEX.test(row);\n  }\n\n  function start_new_row() {\n    table.push({});\n  }\n\n  function parse_fields(row) {\n    var fields = table.last();\n    $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function (field, index) {\n      var column = headings[index].text;\n      var indentation = headings[index].indentation;\n      var text = StringUtils.rtrim(field.substr(indentation));\n      if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n      fields[column] = (fields[column] || []).concat(text);\n    });\n  }\n\n  function collapse(table) {\n    return table\n      .collect(function (row) {\n        var new_row = {};\n        for (var heading in row) {\n          new_row[heading] = row[heading].join('\\n');\n        }\n        return new_row;\n      })\n      .naked();\n  }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  var slice = Array.prototype.slice;\n\n  function curry(ctx, fn) {\n    var args = slice.call(arguments, 2);\n    return function () {\n      return fn.apply(ctx, args.concat(slice.call(arguments)));\n    };\n  }\n\n  function invoke(fn, ctx, args) {\n    return fn.apply(ctx, args);\n  }\n\n  function is_function(object) {\n    var getType = {};\n    return object && getType.toString.call(object) === '[object Function]';\n  }\n\n  function noop() {}\n\n  function noargs(fn) {\n    return function () {\n      return fn();\n    };\n  }\n\n  function asynchronize(ctx, fn) {\n    return function () {\n      var next = slice.call(arguments, arguments.length - 1)[0];\n      var args = slice.call(arguments, 0, arguments.length - 2);\n      fn.apply(ctx, args);\n      if (next) next();\n    };\n  }\n\n  return {\n    noop: noop,\n    noargs: noargs,\n    async_noop: asynchronize(null, noop),\n    asynchronize: asynchronize,\n    is_function: is_function,\n    curry: curry,\n    invoke: invoke,\n  };\n})();\n\n},{}],23:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature|功能',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\n    examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\n    pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\n    only: '(?:[Oo]nly|仅仅?)',\n    background: '[Bb]ackground|背景|前提',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Chinese', vocabulary);\n})();\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n    scenario: '(?:[Ss]cenario|[Gg|eval)',\n    examples: '(?:[Vv]oorbeelden?)',\n    pending: '(?:[Tt]odo|[Mm]oet nog)',\n    only: '(?:[Aa]lleen)',\n    background: '(?:[Aa]chtergrond)',\n    given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n    when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n    then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n    examples: '(?:[Ee]xamples|[Ww]here)',\n    pending: '(?:[Pp]ending|[Tt]odo)',\n    only: '(?:[Oo]nly)',\n    background: '[Bb]ackground',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]onctionnalité)',\n    scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n    examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n    pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n    only: '(?:[Ss]eulement])',\n    background: '(?:[Cc]ontexte)',\n    given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n    when: \"(?:[Qq]uand|[Ll]orsqu'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)\",\n    then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n    _steps: ['given', 'when', 'then', 'soit', 'etantdonnees', 'etantdonnee', 'etantdonne', 'quand', 'lorsque', 'alors'],\n    // Also aliasing French verbs for given-when-then for signature-lookup\n    get soit() {\n      return this.given;\n    },\n    get etantdonnees() {\n      return this.given;\n    },\n    get etantdonnee() {\n      return this.given;\n    },\n    get etantdonne() {\n      return this.given;\n    },\n    get quand() {\n      return this.when;\n    },\n    get lorsque() {\n      return this.when;\n    },\n    get alors() {\n      return this.then;\n    },\n  };\n\n  return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n    scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n    examples: '(?:[Bb]eispiele?)',\n    pending: '(?:[Tt]odo|[Oo]ffen)',\n    only: '(?:[Nn]ur|[Ee]inzig)',\n    background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n    given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n    when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n    then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n'use strict';\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function (name, vocabulary) {\n  var _this = this;\n\n  // See http://github.com/acuminous/yadda#203\n  this.is_language = true;\n\n  this.library = function (dictionary) {\n    return _this.localise_library(new Library(dictionary));\n  };\n\n  this.localise_library = function (library) {\n    $(vocabulary._steps).each(function (keyword) {\n      library[keyword] = function (signatures, fn, ctx, options) {\n        return $(signatures).each(function (signature) {\n          signature = prefix_signature(_this.localise(keyword), signature);\n          return library.define(signature, fn, ctx, options);\n        });\n      };\n    });\n    return library;\n  };\n\n  var prefix_signature = function (prefix, signature) {\n    var regex_delimiters = new RegExp('^/|/$', 'g');\n    var start_of_signature = new RegExp(/^(?:\\^)?/);\n    var one_or_more_spaces = '\\\\s+';\n    var leading_spaces = '^(?:\\\\s)*';\n    return signature\n      .toString()\n      .replace(regex_delimiters, '')\n      .replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n  };\n\n  this.localise = function (keyword) {\n    if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n    return vocabulary[keyword];\n  };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ee]genskap',\n    scenario: '[Ss]cenario',\n    examples: '[Ee]ksempler',\n    pending: '[Aa]vventer',\n    only: '[Bb]are',\n    background: '[Bb]akgrunn',\n    given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n    when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n    then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n    _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n    // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n    get gitt() {\n      return this.given;\n    },\n    get når() {\n      return this.when;\n    },\n    get så() {\n      return this.then;\n    },\n  };\n\n  return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Tt]ale|[Yy]arn)',\n    scenario: '(?:[Aa]dventure|[Ss]ortie)',\n    examples: '[Ww]herest',\n    pending: '[Bb]rig',\n    only: '[Bb]lack [Ss]pot',\n    background: '[Aa]ftground',\n    given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n    // Also aliasing Pirate verbs for given-when-then for signature-lookup\n    get giveth() {\n      return this.given;\n    },\n    get whence() {\n      return this.when;\n    },\n    get thence() {\n      return this.then;\n    },\n  };\n\n  return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n    scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n    examples: '[Pp]rzykłady',\n    pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n    only: '[Tt]ylko',\n    background: '[Zz]ałożenia',\n    given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n    when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n    then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n    _steps: ['given', 'when', 'then', 'zakladajac', 'majac', 'jezeli', 'jesli', 'gdy', 'kiedy', 'wtedy'],\n    // Also aliasing Polish verbs for given-when-then for signature-lookup\n    get zakladajac() {\n      return this.given;\n    },\n    get majac() {\n      return this.given;\n    },\n    get jezeli() {\n      return this.when;\n    },\n    get jesli() {\n      return this.when;\n    },\n    get gdy() {\n      return this.when;\n    },\n    get kiedy() {\n      return this.when;\n    },\n    get wtedy() {\n      return this.then;\n    },\n  };\n\n  return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n    scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n    examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n    pending: '[Pp]endente',\n    only: '[S][óo]',\n    background: '[Ff]undo',\n    given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n    when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n    then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n    _steps: ['given', 'when', 'then', 'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas', 'quando', 'se', 'entao'],\n\n    get seja() {\n      return this.given;\n    },\n    get sejam() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get quando() {\n      return this.when;\n    },\n    get se() {\n      return this.when;\n    },\n    get entao() {\n      return this.then;\n    },\n  };\n\n  return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n    scenario: 'Сценарий',\n    examples: 'Примеры?',\n    pending: '(?:[Ww]ip|[Tt]odo)',\n    only: 'Только',\n    background: '(?:[Пп]редыстория|[Кк]онтекст)',\n    given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n    scenario: '(?:[Ee]scenario|[Cc]aso)',\n    examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n    pending: '[Pp]endiente',\n    only: '[S]ólo',\n    background: '[Ff]ondo',\n    given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n    when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n    then: '(?:[Ee]ntonces)',\n\n    _steps: ['given', 'when', 'then', 'sea', 'sean', 'dado', 'dada', 'dados', 'dadas', 'cuando', 'si', 'entonces'],\n\n    get sea() {\n      return this.given;\n    },\n    get sean() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get cuando() {\n      return this.when;\n    },\n    get si() {\n      return this.when;\n    },\n    get entonces() {\n      return this.then;\n    },\n  };\n\n  return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n    scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n    examples: '[Пп]риклади',\n    pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n    only: '[Тт]ільки',\n    background: '[Кк]онтекст',\n    given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n    when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n    then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  Chinese: require('./Chinese'),\n  English: require('./English'),\n  French: require('./French'),\n  German: require('./German'),\n  Dutch: require('./Dutch'),\n  Norwegian: require('./Norwegian'),\n  Pirate: require('./Pirate'),\n  Ukrainian: require('./Ukrainian'),\n  Polish: require('./Polish'),\n  Spanish: require('./Spanish'),\n  Russian: require('./Russian'),\n  Portuguese: require('./Portuguese'),\n  default: require('./English'),\n  Language: require('./Language'),\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n'use strict';\n\nvar FeatureFileParser = function (options) {\n  var fs = require('../shims').fs;\n  var FeatureParser = require('./FeatureParser');\n  var parser = new FeatureParser(options);\n\n  this.parse = function (file, next) {\n    var text = fs.readFileSync(file, 'utf8');\n    var feature = parser.parse(text);\n    return (next && next(feature)) || feature;\n  };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function (options) {\n  /* eslint-disable no-redeclare */\n  var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']' };\n  var options = options && options.is_language ? { language: options } : options || defaults;\n  var language = options.language || defaults.language;\n  var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n  var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n  /* eslint-enable no-redeclare */\n\n  var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n  var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n  var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n  var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n  var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n  var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n  var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n  var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n  var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n  var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n  var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n  var specification;\n  var comment;\n\n  this.parse = function (text, next) {\n    reset();\n    split(text).each(parse_line);\n    return (next && next(specification.export())) || specification.export();\n  };\n\n  function reset() {\n    specification = new Specification();\n    comment = false;\n  }\n\n  function split(text) {\n    return $(text.split(/\\r\\n|\\n/));\n  }\n\n  function parse_line(line, index) {\n    var match;\n    var line_number = index + 1;\n    try {\n      // eslint-disable-next-line no-return-assign\n      if ((match = MULTI_LINE_COMMENT_REGEX.test(line))) return (comment = !comment);\n      if (comment) return;\n      if ((match = SINGLE_LINE_COMMENT_REGEX.test(line))) return;\n      if ((match = SIMPLE_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n      if ((match = NVP_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n      if ((match = FEATURE_REGEX.exec(line))) return specification.handle('Feature', match[1], line_number);\n      if ((match = SCENARIO_REGEX.exec(line))) return specification.handle('Scenario', match[1], line_number);\n      if ((match = BACKGROUND_REGEX.exec(line))) return specification.handle('Background', match[1], line_number);\n      if ((match = EXAMPLES_REGEX.exec(line))) return specification.handle('Examples', line_number);\n      if ((match = BLANK_REGEX.exec(line))) return specification.handle('Blank', match[0], line_number);\n      if ((match = DASH_REGEX.exec(line))) return specification.handle('Dash', match[1], line_number);\n      if ((match = TEXT_REGEX.exec(line))) return specification.handle('Text', match[1], line_number);\n    } catch (e) {\n      e.message = 'Error parsing line ' + line_number + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n      throw e;\n    }\n  }\n\n  var Handlers = function (handlers) {\n    // eslint-disable-next-line no-redeclare\n    var handlers = handlers || {};\n\n    this.register = function (event, handler) {\n      handlers[event] = handler;\n    };\n\n    this.unregister = function () {\n      $(Array.prototype.slice.call(arguments)).each(function (event) {\n        delete handlers[event];\n      });\n    };\n\n    this.find = function (event) {\n      if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n      return { handle: handlers[event.toLowerCase()] };\n    };\n  };\n\n  var Specification = function () {\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      text: fn.noop,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      feature: start_feature,\n      scenario: start_scenario,\n      background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n      // eslint-disable-next-line no-return-assign\n      return (feature = new Feature(title, annotations, new Annotations()));\n    }\n\n    function start_scenario(event, title, line_number) {\n      feature = new Feature(title, new Annotations(), annotations);\n      return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function (event, data, line_number) {\n      current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      if (!feature) throw new Error('A feature must contain one or more scenarios');\n      return feature.export();\n    };\n  };\n\n  var Annotations = function () {\n    var annotations = {};\n\n    this.stash = function (key, value) {\n      if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n      annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function () {\n      return annotations;\n    };\n  };\n\n  var Feature = function (title, annotations, stashed_annotations) {\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n      text: capture_description,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n      background: start_background,\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n      background = new Background(title, _this);\n      stashed_annotations = new Annotations();\n      return background;\n    }\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background', 'text');\n      stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n      description.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, title) {\n      var scenario = new Scenario(title, background, stashed_annotations, _this);\n      scenarios.push(scenario);\n      stashed_annotations = new Annotations();\n      return scenario;\n    }\n\n    function validate() {\n      if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        scenarios: $(scenarios)\n          .collect(function (scenario) {\n            return scenario.export();\n          })\n          .flatten()\n          .naked(),\n      };\n    };\n  };\n\n  var Background = function (title, feature) {\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n    });\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', stash_annotation);\n      handlers.register('scenario', start_scenario);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      validate();\n      return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        steps: steps,\n      };\n    };\n  };\n\n  var NullBackground = function () {\n    var handlers = new Handlers();\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      return {\n        steps: [],\n      };\n    };\n  };\n\n  var Scenario = function (title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: start_scenario,\n      scenario: start_scenario,\n      examples: start_examples,\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n      handlers.register('examples', start_examples);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n      validate();\n      examples = new Examples(_this);\n      return examples;\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      var result = {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        steps: background.export().steps.concat(steps),\n      };\n      return examples ? examples.expand(result) : result;\n    };\n  };\n\n  var Examples = function (scenario) {\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      blank: fn.noop,\n      dash: start_example_table,\n      text: capture_headings,\n    });\n\n    function start_example_table(evnet, data, line_number) {\n      handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n      handlers.register('annotation', stash_annotation);\n      handlers.register('text', capture_singleline_fields);\n      handlers.register('dash', enable_multiline_examples);\n      var pos = 1;\n      headings = split(data)\n        .collect(function (column) {\n          var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n          pos += column.length + 1;\n          return attributes;\n        })\n        .naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      handlers.unregister('blank', 'dash');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n      handlers.register('dash', end_example_table);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n      annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', continue_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n      parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n      handlers.unregister('text', 'dash');\n      handlers.register('blank', fn.noop);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n      var fields = examples.last().fields;\n      $(headings).each(function (heading) {\n        fields[heading.text + '.index'] = [examples.length];\n        fields[heading.text + '.start.line'] = [line_number];\n        fields[heading.text + '.start.column'] = [heading.left + heading.indentation];\n      });\n    }\n\n    function parse_fields(row, fields) {\n      split(row, headings.length).each(function (field, index) {\n        var column = headings[index].text;\n        var indentation = headings[index].indentation;\n        var text = StringUtils.rtrim(field.substr(indentation));\n        if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n        fields[column] = (fields[column] || []).concat(text);\n      });\n      return fields;\n    }\n\n    function split(row, number_of_fields) {\n      var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n      var fields = $(row.split(separator));\n      if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n        throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n      }\n      return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n      if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function (scenario) {\n      validate();\n      return examples\n        .collect(function (example) {\n          return {\n            title: substitute(example.fields, scenario.title),\n            annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n            description: substitute_all(example, scenario.description),\n            steps: substitute_all(example.fields, scenario.steps),\n          };\n        })\n        .naked();\n    };\n\n    function shallow_merge() {\n      var result = {};\n      $(Array.prototype.slice.call(arguments)).each(function (annotations) {\n        for (var key in annotations) {\n          result[key] = annotations[key];\n        }\n      });\n      return result;\n    }\n\n    function substitute_all(example, lines) {\n      return $(lines)\n        .collect(function (line) {\n          return substitute(example, line);\n        })\n        .naked();\n    }\n\n    function substitute(example, line) {\n      for (var heading in example) {\n        line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n      }\n      return line;\n    }\n  };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\n\nvar StepParser = function () {\n  var NON_BLANK_REGEX = /[^\\s]/;\n\n  this.parse = function (text, next) {\n    var steps = split(text).find_all(non_blanks);\n    return (next && next(steps)) || steps;\n  };\n\n  var split = function (text) {\n    return $(text.split(/\\n/));\n  };\n\n  var non_blanks = function (text) {\n    return text && NON_BLANK_REGEX.test(text);\n  };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  StepParser: require('./StepParser'),\n  FeatureParser: require('./FeatureParser'),\n  FeatureFileParser: require('./FeatureFileParser'),\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){(function (){\n'use strict';\n\nif (!module.client) {\n  var fs = require('../shims').fs;\n  global.process = global.process || {\n    cwd: function () {\n      return fs.workingDirectory;\n    },\n  };\n}\n\nmodule.exports = function (yadda, casper) {\n  var EventBus = require('yadda').EventBus;\n\n  yadda.interpreter.interpret_step = function (step, ctx, next) {\n    var _this = this;\n    casper.then(function () {\n      casper.test.info(step);\n      EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n      _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    });\n  };\n\n  casper.yadda = function (script, ctx) {\n    if (script === undefined) return this;\n    yadda.run(script, ctx);\n  };\n};\n\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  casper: require('./CasperPlugin'),\n  mocha: {\n    ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n    StepLevelPlugin: require('./mocha/StepLevelPlugin'),\n  },\n  get jasmine() {\n    return this.mocha;\n  },\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n'use strict';\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function (options) {\n  /* jslint shadow: true */\n  var platform = new Platform();\n  var language = options.language || Localisation.default;\n  var parser = options.parser || new FeatureFileParser(language);\n  var container = options.container || platform.get_container();\n\n  function featureFiles(files, iterator) {\n    $(files).each(function (file) {\n      features(parser.parse(file), iterator);\n    });\n  }\n\n  function features(features, iterator) {\n    $(features).each(function (feature) {\n      describe(feature.title, feature, iterator);\n    });\n  }\n\n  function describe(title, subject, iterator) {\n    var _describe = getDescribe(subject.annotations);\n    _describe(title, function () {\n      iterator(subject);\n    });\n  }\n\n  function it_async(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function (done) {\n      iterator(this, subject, done);\n    });\n  }\n\n  function it_sync(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function () {\n      iterator(this, subject);\n    });\n  }\n\n  function getIt(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xit;\n    if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n    return container.it;\n  }\n\n  function getDescribe(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xdescribe;\n    if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n    return container.describe;\n  }\n\n  function has_annotation(annotations, name) {\n    var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n    for (var key in annotations) {\n      if (regexp.test(key)) return true;\n    }\n  }\n\n  return {\n    featureFiles: featureFiles,\n    features: features,\n    describe: describe,\n    it_async: it_async,\n    it_sync: it_sync,\n  };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n      itFn(scenario.title, scenario, function (context, scenario, done) {\n        iterator(scenario, done);\n      });\n    });\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      base_plugin.describe(scenario.title, scenario, iterator);\n    });\n  }\n\n  function steps(steps, iterator) {\n    var abort = false;\n\n    $(steps).each(function (step) {\n      var stepFn = iterator.length === 1 ? step_sync : step_async;\n      stepFn(step, iterator);\n    });\n\n    function step_async(step, iterator) {\n      base_plugin.it_async(step, step, function (context, step, done) {\n        if (abort) {\n          return context.skip ? context.skip() : done();\n        }\n        abort = true;\n        iterator.bind(context)(step, function (err) {\n          if (err) return (done.fail || done)(err);\n          abort = false;\n          done();\n        });\n      });\n    }\n\n    function step_sync(step, iterator) {\n      base_plugin.it_sync(step, step, function (context, step) {\n        if (abort) return context.skip && context.skip();\n        abort = true;\n        iterator.bind(context)(step);\n        abort = false;\n      });\n    }\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n  container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n'use strict';\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function (s1, s2) {\n  this.value;\n  this.type = 'LevenshteinDistanceScore';\n  var distance_table;\n  var _this = this;\n\n  var initialise = function () {\n    var x = s1.length;\n    var y = s2.length;\n\n    distance_table = new Array(x + 1);\n\n    /* eslint-disable no-redeclare */\n    for (var i = 0; i <= x; i++) {\n      distance_table[i] = new Array(y + 1);\n    }\n\n    for (var i = 0; i <= x; i++) {\n      for (var j = 0; j <= y; j++) {\n        distance_table[i][j] = 0;\n      }\n    }\n\n    for (var i = 0; i <= x; i++) {\n      distance_table[i][0] = i;\n    }\n\n    for (var j = 0; j <= y; j++) {\n      distance_table[0][j] = j;\n    }\n    /* eslint-enable no-redeclare */\n  };\n\n  var score = function () {\n    // eslint-disable-next-line no-return-assign\n    if (s1 === s2) return (_this.value = 0);\n\n    for (var j = 0; j < s2.length; j++) {\n      for (var i = 0; i < s1.length; i++) {\n        if (s1[i] === s2[j]) {\n          distance_table[i + 1][j + 1] = distance_table[i][j];\n        } else {\n          var deletion = distance_table[i][j + 1] + 1;\n          var insertion = distance_table[i + 1][j] + 1;\n          var substitution = distance_table[i][j] + 1;\n          distance_table[i + 1][j + 1] = Math.min(substitution, deletion, insertion);\n        }\n      }\n    }\n    _this.value = distance_table[s1.length][s2.length];\n  };\n\n  this.compare = function (other) {\n    return other.value - this.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n\n  initialise();\n  score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\n\nvar MultiScore = function (scores) {\n  this.scores = $(scores);\n  this.type = 'MultiScore';\n\n  this.compare = function (other) {\n    for (var i = 0; i < this.scores.length; i++) {\n      var difference = this.scores[i].compare(other.scores[i]);\n      if (difference) return difference;\n    }\n    return 0;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    if (this.type !== other.type) return false;\n    return this.compare(other) === 0;\n  };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n'use strict';\n\nvar SameLibraryScore = function (m1, m2) {\n  this.value = m1.is_sibling(m2) ? 1 : 0;\n  this.type = 'SameLibraryScore';\n\n  this.compare = function (other) {\n    return this.value - other.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){(function (){\n'use strict';\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n  var platform = new Platform();\n\n  var shims = {\n    node: function () {\n      return {\n        fs: require('fs'),\n        path: require('path'),\n        process: process,\n      };\n    },\n    phantom: function () {\n      return {\n        fs: require('./phantom-fs'),\n        path: require('./phantom-path'),\n        process: require('./phantom-process'),\n      };\n    },\n    karma: function () {\n      return {\n        fs: require('./karma-fs'),\n        path: require('./karma-path'),\n        process: require('./karma-process'),\n      };\n    },\n  };\n\n  function get_shim() {\n    if (platform.is_phantom()) return shims.phantom();\n    if (platform.is_browser() && platform.is_karma()) return shims.karma();\n    if (platform.is_node()) return shims.node();\n    return {};\n  }\n\n  return get_shim();\n})();\n\n}).call(this)}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var path = require('./karma-path');\n\n  function absolutePath(relativePath) {\n    return path.resolve(path.normalize(relativePath.split('\\\\').join('/')));\n  }\n\n  var KarmaFileSystem = function () {\n    this.registry = new KarmaPathRegistry();\n    this.converter = new KarmaUriPathConverter('/base/', '/');\n    this.reader = new KarmaFileReader(this.converter);\n\n    var servedUris = Object.keys(window.__karma__.files);\n    var servedFiles = this.converter.parseUris(servedUris);\n    servedFiles.forEach(this.registry.addFile, this.registry);\n  };\n  KarmaFileSystem.prototype = {\n    constructor: KarmaFileSystem,\n    workingDirectory: '/',\n    existsSync: function (path) {\n      return this.registry.exists(path);\n    },\n    readdirSync: function (path) {\n      return this.registry.getContent(path);\n    },\n    statSync: function (path) {\n      return {\n        isDirectory: function () {\n          return this.registry.isDirectory(path);\n        }.bind(this),\n      };\n    },\n    readFileSync: function (file, encoding) {\n      if (encoding !== 'utf8') throw new Error('This fs.readFileSync() shim does not support other than utf8 encoding.');\n      if (!this.registry.isFile(file)) throw new Error('File does not exist: ' + file);\n      return this.reader.readFile(file);\n    },\n  };\n\n  var KarmaPathRegistry = function KarmaPathRegistry() {\n    this.paths = {};\n  };\n\n  KarmaPathRegistry.prototype = {\n    constructor: KarmaPathRegistry,\n    addFile: function (file) {\n      file = absolutePath(file);\n      this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n      var parentDirectory = path.dirname(file);\n      this.addDirectory(parentDirectory);\n    },\n    addDirectory: function (directory) {\n      directory = absolutePath(directory);\n      this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n      var parentDirectory = path.dirname(directory);\n      if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n    },\n    isFile: function (file) {\n      file = absolutePath(file);\n      return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n    },\n    isDirectory: function (directory) {\n      directory = absolutePath(directory);\n      return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n    },\n    exists: function (node) {\n      node = absolutePath(node);\n      return this.paths.hasOwnProperty(node);\n    },\n    getContent: function (directory) {\n      if (!this.isDirectory(directory)) throw new Error('Not a directory: ' + directory);\n      directory = absolutePath(directory);\n      return Object.keys(this.paths)\n        .filter(function (node) {\n          if (node === directory) return false;\n          var parentDirectory = path.dirname(node);\n          return parentDirectory === directory;\n        }, this)\n        .map(function (node) {\n          return path.basename(node);\n        });\n    },\n  };\n\n  KarmaPathRegistry.TYPE_FILE = 0;\n  KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n  var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n    this.workingDirectory = workingDirectory;\n    this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n    this.baseUri = baseUri;\n    this.baseUriPattern = this.patternFromBase(baseUri);\n  };\n\n  KarmaUriPathConverter.prototype = {\n    constructor: KarmaUriPathConverter,\n    patternFromBase: function (string, flags) {\n      var pattern = '^' + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n      return new RegExp(pattern, flags);\n    },\n    parseUris: function (uris) {\n      return uris\n        .filter(function (uri) {\n          return this.baseUriPattern.test(uri);\n        }, this)\n        .map(function (uri) {\n          return uri.replace(this.baseUriPattern, this.workingDirectory);\n        }, this);\n    },\n    buildUri: function (file) {\n      file = absolutePath(file);\n      if (!this.workingDirectoryPattern.test(file)) throw new Error('Path is not in working directory: ' + file);\n      return file.replace(this.workingDirectoryPattern, this.baseUri);\n    },\n  };\n\n  var KarmaFileReader = function KarmaFileReader(converter) {\n    this.converter = converter;\n  };\n\n  KarmaFileReader.prototype = {\n    constructor: KarmaFileReader,\n    readFile: function (file) {\n      var uri = this.converter.buildUri(file);\n      // eslint-disable-next-line no-undef\n      var xhr = new XMLHttpRequest();\n      xhr.open('get', uri, false);\n      xhr.send();\n      return xhr.responseText;\n    },\n  };\n\n  return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n  }\n\n  if (typeof path.normalize !== 'function' || typeof path.dirname !== 'function') throw new Error('The path module emulation does not contain implementations of required functions.');\n\n  return path;\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var fs = require('./karma-fs');\n  var process = {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n\n  fs.existsSync = fs.existsSync || fs.exists;\n\n  fs.readdirSync =\n    fs.readdirSync ||\n    function (path) {\n      return fs.list(path).filter(function (name) {\n        return name !== '.' && name !== '..';\n      });\n    };\n\n  fs.statSync =\n    fs.statSync ||\n    function (path) {\n      return {\n        isDirectory: function () {\n          return fs.isDirectory(path);\n        },\n      };\n    };\n\n  return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    // meh\n  }\n\n  path.join =\n    path.join ||\n    function () {\n      return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n  path.relative =\n    path.relative ||\n    function (from, to) {\n      return from + fs.separator + to;\n    };\n\n  return path;\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var process = typeof process !== 'undefined' ? process : {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){(function (){\n// 'path' module extracted from Node.js v8.11.1 (only the posix part)\n// transplited with Babel\n\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nfunction assertPath(path) {\n  if (typeof path !== 'string') {\n    throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));\n  }\n}\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeStringPosix(path, allowAboveRoot) {\n  var res = '';\n  var lastSegmentLength = 0;\n  var lastSlash = -1;\n  var dots = 0;\n  var code;\n  for (var i = 0; i <= path.length; ++i) {\n    if (i < path.length)\n      code = path.charCodeAt(i);\n    else if (code === 47 /*/*/)\n      break;\n    else\n      code = 47 /*/*/;\n    if (code === 47 /*/*/) {\n      if (lastSlash === i - 1 || dots === 1) {\n        // NOOP\n      } else if (lastSlash !== i - 1 && dots === 2) {\n        if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {\n          if (res.length > 2) {\n            var lastSlashIndex = res.lastIndexOf('/');\n            if (lastSlashIndex !== res.length - 1) {\n              if (lastSlashIndex === -1) {\n                res = '';\n                lastSegmentLength = 0;\n              } else {\n                res = res.slice(0, lastSlashIndex);\n                lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n              }\n              lastSlash = i;\n              dots = 0;\n              continue;\n            }\n          } else if (res.length === 2 || res.length === 1) {\n            res = '';\n            lastSegmentLength = 0;\n            lastSlash = i;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          if (res.length > 0)\n            res += '/..';\n          else\n            res = '..';\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0)\n          res += '/' + path.slice(lastSlash + 1, i);\n        else\n          res = path.slice(lastSlash + 1, i);\n        lastSegmentLength = i - lastSlash - 1;\n      }\n      lastSlash = i;\n      dots = 0;\n    } else if (code === 46 /*.*/ && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\n\nfunction _format(sep, pathObject) {\n  var dir = pathObject.dir || pathObject.root;\n  var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');\n  if (!dir) {\n    return base;\n  }\n  if (dir === pathObject.root) {\n    return dir + base;\n  }\n  return dir + sep + base;\n}\n\nvar posix = {\n  // path.resolve([from ...], to)\n  resolve: function resolve() {\n    var resolvedPath = '';\n    var resolvedAbsolute = false;\n    var cwd;\n\n    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n      var path;\n      if (i >= 0)\n        path = arguments[i];\n      else {\n        if (cwd === undefined)\n          cwd = process.cwd();\n        path = cwd;\n      }\n\n      assertPath(path);\n\n      // Skip empty entries\n      if (path.length === 0) {\n        continue;\n      }\n\n      resolvedPath = path + '/' + resolvedPath;\n      resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    }\n\n    // At this point the path should be resolved to a full absolute path, but\n    // handle relative paths to be safe (might happen when process.cwd() fails)\n\n    // Normalize the path\n    resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);\n\n    if (resolvedAbsolute) {\n      if (resolvedPath.length > 0)\n        return '/' + resolvedPath;\n      else\n        return '/';\n    } else if (resolvedPath.length > 0) {\n      return resolvedPath;\n    } else {\n      return '.';\n    }\n  },\n\n  normalize: function normalize(path) {\n    assertPath(path);\n\n    if (path.length === 0) return '.';\n\n    var isAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;\n\n    // Normalize the path\n    path = normalizeStringPosix(path, !isAbsolute);\n\n    if (path.length === 0 && !isAbsolute) path = '.';\n    if (path.length > 0 && trailingSeparator) path += '/';\n\n    if (isAbsolute) return '/' + path;\n    return path;\n  },\n\n  isAbsolute: function isAbsolute(path) {\n    assertPath(path);\n    return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;\n  },\n\n  join: function join() {\n    if (arguments.length === 0)\n      return '.';\n    var joined;\n    for (var i = 0; i < arguments.length; ++i) {\n      var arg = arguments[i];\n      assertPath(arg);\n      if (arg.length > 0) {\n        if (joined === undefined)\n          joined = arg;\n        else\n          joined += '/' + arg;\n      }\n    }\n    if (joined === undefined)\n      return '.';\n    return posix.normalize(joined);\n  },\n\n  relative: function relative(from, to) {\n    assertPath(from);\n    assertPath(to);\n\n    if (from === to) return '';\n\n    from = posix.resolve(from);\n    to = posix.resolve(to);\n\n    if (from === to) return '';\n\n    // Trim any leading backslashes\n    var fromStart = 1;\n    for (; fromStart < from.length; ++fromStart) {\n      if (from.charCodeAt(fromStart) !== 47 /*/*/)\n        break;\n    }\n    var fromEnd = from.length;\n    var fromLen = fromEnd - fromStart;\n\n    // Trim any leading backslashes\n    var toStart = 1;\n    for (; toStart < to.length; ++toStart) {\n      if (to.charCodeAt(toStart) !== 47 /*/*/)\n        break;\n    }\n    var toEnd = to.length;\n    var toLen = toEnd - toStart;\n\n    // Compare paths to find the longest common path from root\n    var length = fromLen < toLen ? fromLen : toLen;\n    var lastCommonSep = -1;\n    var i = 0;\n    for (; i <= length; ++i) {\n      if (i === length) {\n        if (toLen > length) {\n          if (to.charCodeAt(toStart + i) === 47 /*/*/) {\n            // We get here if `from` is the exact base path for `to`.\n            // For example: from='/foo/bar'; to='/foo/bar/baz'\n            return to.slice(toStart + i + 1);\n          } else if (i === 0) {\n            // We get here if `from` is the root\n            // For example: from='/'; to='/foo'\n            return to.slice(toStart + i);\n          }\n        } else if (fromLen > length) {\n          if (from.charCodeAt(fromStart + i) === 47 /*/*/) {\n            // We get here if `to` is the exact base path for `from`.\n            // For example: from='/foo/bar/baz'; to='/foo/bar'\n            lastCommonSep = i;\n          } else if (i === 0) {\n            // We get here if `to` is the root.\n            // For example: from='/foo'; to='/'\n            lastCommonSep = 0;\n          }\n        }\n        break;\n      }\n      var fromCode = from.charCodeAt(fromStart + i);\n      var toCode = to.charCodeAt(toStart + i);\n      if (fromCode !== toCode)\n        break;\n      else if (fromCode === 47 /*/*/)\n        lastCommonSep = i;\n    }\n\n    var out = '';\n    // Generate the relative path based on the path difference between `to`\n    // and `from`\n    for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n      if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {\n        if (out.length === 0)\n          out += '..';\n        else\n          out += '/..';\n      }\n    }\n\n    // Lastly, append the rest of the destination (`to`) path that comes after\n    // the common path parts\n    if (out.length > 0)\n      return out + to.slice(toStart + lastCommonSep);\n    else {\n      toStart += lastCommonSep;\n      if (to.charCodeAt(toStart) === 47 /*/*/)\n        ++toStart;\n      return to.slice(toStart);\n    }\n  },\n\n  _makeLong: function _makeLong(path) {\n    return path;\n  },\n\n  dirname: function dirname(path) {\n    assertPath(path);\n    if (path.length === 0) return '.';\n    var code = path.charCodeAt(0);\n    var hasRoot = code === 47 /*/*/;\n    var end = -1;\n    var matchedSlash = true;\n    for (var i = path.length - 1; i >= 1; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          if (!matchedSlash) {\n            end = i;\n            break;\n          }\n        } else {\n        // We saw the first non-path separator\n        matchedSlash = false;\n      }\n    }\n\n    if (end === -1) return hasRoot ? '/' : '.';\n    if (hasRoot && end === 1) return '//';\n    return path.slice(0, end);\n  },\n\n  basename: function basename(path, ext) {\n    if (ext !== undefined && typeof ext !== 'string') throw new TypeError('\"ext\" argument must be a string');\n    assertPath(path);\n\n    var start = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i;\n\n    if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n      if (ext.length === path.length && ext === path) return '';\n      var extIdx = ext.length - 1;\n      var firstNonSlashEnd = -1;\n      for (i = path.length - 1; i >= 0; --i) {\n        var code = path.charCodeAt(i);\n        if (code === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else {\n          if (firstNonSlashEnd === -1) {\n            // We saw the first non-path separator, remember this index in case\n            // we need it if the extension ends up not matching\n            matchedSlash = false;\n            firstNonSlashEnd = i + 1;\n          }\n          if (extIdx >= 0) {\n            // Try to match the explicit extension\n            if (code === ext.charCodeAt(extIdx)) {\n              if (--extIdx === -1) {\n                // We matched the extension, so mark this as the end of our path\n                // component\n                end = i;\n              }\n            } else {\n              // Extension does not match, so our result is the entire path\n              // component\n              extIdx = -1;\n              end = firstNonSlashEnd;\n            }\n          }\n        }\n      }\n\n      if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;\n      return path.slice(start, end);\n    } else {\n      for (i = path.length - 1; i >= 0; --i) {\n        if (path.charCodeAt(i) === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else if (end === -1) {\n          // We saw the first non-path separator, mark this as the end of our\n          // path component\n          matchedSlash = false;\n          end = i + 1;\n        }\n      }\n\n      if (end === -1) return '';\n      return path.slice(start, end);\n    }\n  },\n\n  extname: function extname(path) {\n    assertPath(path);\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n    for (var i = path.length - 1; i >= 0; --i) {\n      var code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1)\n            startDot = i;\n          else if (preDotState !== 1)\n            preDotState = 1;\n      } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n        // We saw a non-dot character immediately before the dot\n        preDotState === 0 ||\n        // The (right-most) trimmed path component is exactly '..'\n        preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      return '';\n    }\n    return path.slice(startDot, end);\n  },\n\n  format: function format(pathObject) {\n    if (pathObject === null || typeof pathObject !== 'object') {\n      throw new TypeError('The \"pathObject\" argument must be of type Object. Received type ' + typeof pathObject);\n    }\n    return _format('/', pathObject);\n  },\n\n  parse: function parse(path) {\n    assertPath(path);\n\n    var ret = { root: '', dir: '', base: '', ext: '', name: '' };\n    if (path.length === 0) return ret;\n    var code = path.charCodeAt(0);\n    var isAbsolute = code === 47 /*/*/;\n    var start;\n    if (isAbsolute) {\n      ret.root = '/';\n      start = 1;\n    } else {\n      start = 0;\n    }\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i = path.length - 1;\n\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n\n    // Get non-dir info\n    for (; i >= start; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;\n        } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n    // We saw a non-dot character immediately before the dot\n    preDotState === 0 ||\n    // The (right-most) trimmed path component is exactly '..'\n    preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      if (end !== -1) {\n        if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);\n      }\n    } else {\n      if (startPart === 0 && isAbsolute) {\n        ret.name = path.slice(1, startDot);\n        ret.base = path.slice(1, end);\n      } else {\n        ret.name = path.slice(startPart, startDot);\n        ret.base = path.slice(startPart, end);\n      }\n      ret.ext = path.slice(startDot, end);\n    }\n\n    if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';\n\n    return ret;\n  },\n\n  sep: '/',\n  delimiter: ':',\n  win32: null,\n  posix: null\n};\n\nposix.posix = posix;\n\nmodule.exports = posix;\n\n}).call(this)}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n'use strict';\n\nvar api = {\n  Yadda: require('./Yadda'),\n  EventBus: require('./EventBus'),\n  Interpreter: require('./Interpreter'),\n  Context: require('./Context'),\n  Library: require('./Library'),\n  Dictionary: require('./Dictionary'),\n  FeatureFileSearch: require('./FeatureFileSearch'),\n  FileSearch: require('./FileSearch'),\n  Platform: require('./Platform'),\n  localisation: require('./localisation/index'),\n  converters: require('./converters/index'),\n  parsers: require('./parsers/index'),\n  plugins: require('./plugins/index'),\n  shims: require('./shims/index'),\n  createInstance: function () {\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n  },\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "dist/yadda-umd-2.2.0.js",
    "content": "require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\n'use strict';\n\nvar fn = require('./fn');\n\nmodule.exports = function (obj) {\n  function ensure_array(obj) {\n    var array = obj ? [].concat(obj) : [];\n    array.in_array = fn.curry(array, in_array, array);\n    array.each = fn.curry(array, each, array);\n    array.each_async = fn.curry(array, each_async, array);\n    array.collect = fn.curry(array, collect, array);\n    array.collect_async = fn.curry(array, collect_async, array);\n    array.flatten = fn.curry(array, flatten, array);\n    array.inject = fn.curry(array, inject, array);\n    array.push_all = fn.curry(array, push_all, array);\n    array.fill = fn.curry(array, fill, array);\n    array.find_all = fn.curry(array, find_all, array);\n    array.find = fn.curry(array, find, array);\n    array.last = fn.curry(array, last, array);\n    array.naked = fn.curry(array, naked, array);\n    return array;\n  }\n\n  function is_array(obj) {\n    return Object.prototype.toString.call(obj) === '[object Array]';\n  }\n\n  function in_array(items, item) {\n    for (var i = 0; i < items.length; i++) {\n      if (items[i] === item) {\n        return true;\n      }\n    }\n  }\n\n  function flatten(items) {\n    if (!is_array(items)) return [items];\n    if (items.length === 0) return items;\n    var head = flatten(items[0]);\n    var tail = flatten(items.slice(1));\n    return ensure_array(head.concat(tail));\n  }\n\n  function each(items, iterator) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(items[i], i);\n    }\n    return result;\n  }\n\n  function each_async(items, iterator, callback) {\n    callback = callback || fn.noop;\n    if (!items.length) return callback();\n    var index = 0;\n    var iterate = function () {\n      iterator(items[index], index, function (err, result) {\n        if (err) return callback(err);\n        if (++index >= items.length) return callback(null, result);\n        iterate();\n      });\n    };\n    iterate();\n  }\n\n  function collect(items, iterator) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      results.push(iterator(items[i], i));\n    }\n    return results;\n  }\n\n  function collect_async(items, iterator, callback) {\n    var results = ensure_array();\n    each_async(\n      items,\n      function (item, index, each_callback) {\n        iterator(item, index, function (err) {\n          if (err) return each_callback(err);\n          results.push_all(Array.prototype.splice.call(arguments, 1));\n          each_callback();\n        });\n      },\n      function (err) {\n        if (err) return callback(err);\n        callback(null, results);\n      }\n    );\n  }\n\n  function inject(items, default_value, iterator) {\n    var result = default_value;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(result, items[i]);\n    }\n    return result;\n  }\n\n  function push_all(items, more_items) {\n    more_items = more_items ? [].concat(more_items) : [];\n    for (var i = 0; i < more_items.length; i++) {\n      items.push(more_items[i]);\n    }\n    return items;\n  }\n\n  function fill(items, item, num) {\n    for (var i = 0; i < num; i++) {\n      items.push(item);\n    }\n    return items;\n  }\n\n  function find_all(items, test) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        results.push(items[i]);\n      }\n    }\n    return results;\n  }\n\n  function find(items, test) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        result = items[i];\n        break;\n      }\n    }\n    return result;\n  }\n\n  function last(items) {\n    return items[items.length - 1];\n  }\n\n  function naked(items) {\n    return [].concat(items);\n  }\n\n  return ensure_array(obj);\n};\n\n},{\"./fn\":22}],2:[function(require,module,exports){\n'use strict';\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function (step, macros, last_macro) {\n  var results = [];\n\n  this.validate = function () {\n    if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n    if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n    return { step: step, valid: true, winner: this.winner() };\n  };\n\n  this.clear_winner = function () {\n    if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n    if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n    return this.winner();\n  };\n\n  function is_undefined() {\n    return results.length === 0;\n  }\n\n  function is_ambiguous() {\n    return results.length > 1 && results[0].score.equals(results[1].score);\n  }\n\n  this.winner = function () {\n    return results[0].macro;\n  };\n\n  function winning_patterns() {\n    return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n  }\n\n  function rank(step, macros) {\n    results = macros\n      .collect(function (macro) {\n        return {\n          macro: macro,\n          score: new MultiScore([new LevenshteinDistanceScore(step, macro.levenshtein_signature()), new SameLibraryScore(macro, last_macro)]),\n        };\n      })\n      .sort(by_ascending_score);\n  }\n\n  function by_ascending_score(a, b) {\n    return b.score.compare(a.score);\n  }\n\n  function by_winning_score(result) {\n    return result.score.equals(results[0].score);\n  }\n\n  function macro_signatures(result) {\n    return result.macro.toString();\n  }\n\n  rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n\n},{\"./Array\":1,\"./scores/LevenshteinDistanceScore\":46,\"./scores/MultiScore\":47,\"./scores/SameLibraryScore\":48}],3:[function(require,module,exports){\n'use strict';\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function (properties) {\n  // I was previously getting some weird errors using instanceof to determine if\n  // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n  this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n  this.properties = {};\n\n  this.merge = function (other) {\n    if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n    return new Context(this.properties)._merge(other);\n  };\n\n  this._merge = function (other) {\n    for (var key in other) {\n      this.properties[key] = other[key];\n    }\n    return this;\n  };\n\n  this._merge(properties);\n};\n\nmodule.exports = Context;\n\n},{}],4:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function (prefix) {\n  // eslint-disable-next-line no-redeclare\n  var prefix = prefix || '$';\n  var definitions = {};\n  var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n  var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n  var _this = this;\n\n  this.define = function (term, pattern, converters) {\n    if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n    if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n    if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n    if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n    definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n    return this;\n  };\n\n  this.merge = function (other) {\n    if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n    return new Dictionary(prefix)._merge(this)._merge(other);\n  };\n\n  this._merge = function (other) {\n    other.each(function (term, definition) {\n      _this.define(term, definition.pattern);\n    });\n    return this;\n  };\n\n  this._prefix = function () {\n    return prefix;\n  };\n\n  this.each = function (callback) {\n    for (var term in definitions) {\n      callback(term, definitions[term]);\n    }\n  };\n\n  this.expand = function (signature, already_expanding) {\n    var text = normalise(signature);\n    return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) } : { pattern: text, converters: get_converters(text) };\n  };\n\n  function expand_sub_terms(text, already_expanding) {\n    return get_sub_terms(text).each(function (sub_term) {\n      if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n      var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n      text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n      return text;\n    });\n  }\n\n  function get_sub_terms(text) {\n    return term_grouping_pattern.groups(text);\n  }\n\n  function expand_sub_term(sub_term, already_expanding) {\n    var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n    return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n  }\n\n  function normalise(pattern) {\n    return pattern.toString().replace(/^\\/|\\/$/g, '');\n  }\n\n  function is_defined(term) {\n    return !!definitions[term];\n  }\n\n  function is_expandable(text) {\n    return term_grouping_pattern.test(text);\n  }\n\n  function is_compatible(converters, pattern) {\n    return count_converter_arguments(converters) === count_matching_groups(pattern);\n  }\n\n  function get_converters(text) {\n    return $(text.split(term_splitting_pattern)).inject($(), function (converters, fragment) {\n      return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment) : get_matching_group_converters(fragment));\n    });\n  }\n\n  function get_matching_group_converters(text) {\n    return $().fill(pass_through_converter, count_matching_groups(text));\n  }\n\n  function get_sub_term_converters(text) {\n    return get_sub_terms(text).inject($(), function (converters, sub_term) {\n      return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters) : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n    });\n  }\n\n  function count_matching_groups(pattern) {\n    return new RegExp(pattern + '|').exec('').length - 1;\n  }\n\n  function count_converter_arguments(converters) {\n    return $(converters).inject(0, function (sum, converter) {\n      return sum + converter.length - 1;\n    });\n  }\n};\n\nmodule.exports = Dictionary;\n\n},{\"./Array\":1,\"./RegularExpression\":12,\"./converters/pass-through-converter\":20}],5:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n  var event_handlers = $();\n\n  this.send = function (event_name, event_data, next) {\n    if (arguments.length === 1) return this.send(event_name, {});\n    if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n    notify_handlers(event_name, event_data);\n    next && next();\n    return this;\n  };\n\n  this.on = function (event_pattern, callback) {\n    event_handlers.push({ pattern: event_pattern, callback: callback });\n    return this;\n  };\n\n  var notify_handlers = function (event_name, event_data) {\n    find_handlers(event_name).each(function (callback) {\n      callback({ name: event_name, data: event_data });\n    });\n  };\n\n  var find_handlers = function (event_name) {\n    return event_handlers\n      .find_all(function (handler) {\n        return new RegExp(handler.pattern).test(event_name);\n      })\n      .collect(function (handler) {\n        return handler.callback;\n      });\n  };\n}\n\nfunction instance() {\n  return event_bus;\n}\n\nmodule.exports = {\n  instance: instance,\n  ON_SCENARIO: '__ON_SCENARIO__',\n  ON_STEP: '__ON_STEP__',\n  ON_EXECUTE: '__ON_EXECUTE__',\n  ON_DEFINE: '__ON_DEFINE__',\n};\n\n},{\"./Array\":1,\"./fn\":22}],6:[function(require,module,exports){\n'use strict';\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function (directories) {\n  this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n\n},{\"./FileSearch\":7}],7:[function(require,module,exports){\n'use strict';\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function (directories, patterns) {\n  // eslint-disable-next-line no-redeclare\n  var patterns = patterns || /.*/;\n\n  this.each = function (fn) {\n    this.list().forEach(fn);\n  };\n\n  this.list = function () {\n    return $(directories).inject($(), function (files, directory) {\n      return files.concat(list_files(directory).find_all(by_pattern));\n    });\n  };\n\n  var list_files = function (directory) {\n    return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n  };\n\n  var list_immediate_files = function (directory) {\n    return ls(directory).find_all(by_file);\n  };\n\n  var list_sub_directory_files = function (directory) {\n    return ls(directory)\n      .find_all(by_directory)\n      .inject($(), function (files, directory) {\n        return files.concat(list_files(directory));\n      });\n  };\n\n  var ls = function (directory) {\n    if (!fs.existsSync(directory)) return $();\n    return $(fs.readdirSync(directory)).collect(function (file) {\n      return path.join(directory, file);\n    });\n  };\n\n  var by_file = function (file) {\n    return !by_directory(file);\n  };\n\n  var by_directory = function (file) {\n    return fs.statSync(file).isDirectory();\n  };\n\n  var by_pattern = function (filename) {\n    return $(patterns).find(function (pattern) {\n      return new RegExp(pattern).test(filename);\n    });\n  };\n};\n\nmodule.exports = FileSearch;\n\n},{\"./Array\":1,\"./shims/index\":49}],8:[function(require,module,exports){\n'use strict';\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function (libraries) {\n  // eslint-disable-next-line no-redeclare\n  var libraries = $(libraries);\n  var event_bus = EventBus.instance();\n  var last_macro;\n  var _this = this;\n\n  this.requires = function (libs) {\n    libraries.push_all(libs);\n    return this;\n  };\n\n  this.validate = function (scenario) {\n    var results = $(scenario).collect(function (step) {\n      var report = _this.rank_macros(step).validate();\n      last_macro = report.winner;\n      return report;\n    });\n    if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n  };\n\n  function by_invalid_step(result) {\n    return !result.valid;\n  }\n\n  function validation_report(result) {\n    return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n  }\n\n  this.interpret = function (scenario, scenario_context, next) {\n    scenario_context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n    var iterator = make_step_iterator(scenario_context, next);\n    $(scenario).each_async(iterator, next);\n  };\n\n  var make_step_iterator = function (scenario_context, next) {\n    var iterator = function (step, index, callback) {\n      _this.interpret_step(step, scenario_context, callback);\n    };\n    return next ? iterator : fn.asynchronize(null, iterator);\n  };\n\n  this.interpret_step = function (step, scenario_context, next) {\n    var context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n    var macro = this.rank_macros(step).clear_winner();\n    last_macro = macro;\n    macro.interpret(step, context || {}, next);\n  };\n\n  this.rank_macros = function (step) {\n    return new Competition(step, compatible_macros(step), last_macro);\n  };\n\n  var compatible_macros = function (step) {\n    return libraries.inject([], function (macros, library) {\n      return macros.concat(library.find_compatible_macros(step));\n    });\n  };\n};\n\nmodule.exports = Interpreter;\n\n},{\"./Array\":1,\"./Competition\":2,\"./Context\":3,\"./EventBus\":5,\"./fn\":22}],9:[function(require,module,exports){\n'use strict';\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function (dictionary) {\n  // eslint-disable-next-line no-redeclare\n  var dictionary = dictionary || new Dictionary();\n  var macros = $();\n  var _this = this;\n\n  this.define = function (signatures, fn, macro_context, options) {\n    $(signatures).each(function (signature) {\n      define_macro(signature, fn, macro_context, options);\n    });\n    return this;\n  };\n\n  var define_macro = function (signature, fn, macro_context, options) {\n    if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n    macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n  };\n\n  this.get_macro = function (signature) {\n    return macros.find(function (other_macro) {\n      return other_macro.is_identified_by(signature);\n    });\n  };\n\n  this.find_compatible_macros = function (step) {\n    return macros.find_all(function (macro) {\n      return macro.can_interpret(step);\n    });\n  };\n};\n\nmodule.exports = Library;\n\n},{\"./Array\":1,\"./Dictionary\":4,\"./Macro\":10}],10:[function(require,module,exports){\n'use strict';\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function (signature, parsed_signature, macro, macro_context, library, options) {\n  /* eslint-disable no-redeclare */\n  var signature = normalise(signature);\n  var signature_pattern = new RegularExpression(parsed_signature.pattern);\n  var macro = macro || fn.async_noop;\n  var event_bus = EventBus.instance();\n  var options = options || {};\n  /* eslint-enable no-redeclare */\n\n  this.library = library;\n\n  this.is_identified_by = function (other_signature) {\n    return signature === normalise(other_signature);\n  };\n\n  this.can_interpret = function (step) {\n    return signature_pattern.test(step);\n  };\n\n  this.interpret = function (step, scenario_context, next) {\n    var context = new Context({ step: step }).merge(macro_context).merge(scenario_context);\n    convert(signature_pattern.groups(step), function (err, args) {\n      if (err) return next(err);\n      event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n      var result;\n      try {\n        result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n      } catch (err) {\n        if (next) return next(err);\n        throw err;\n      }\n      if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n      if (is_sync(args)) return next && next();\n    });\n  };\n\n  this.is_sibling = function (other_macro) {\n    return other_macro && other_macro.defined_in(library);\n  };\n\n  this.defined_in = function (other_library) {\n    return library === other_library;\n  };\n\n  this.levenshtein_signature = function () {\n    return signature_pattern.without_expressions();\n  };\n\n  this.toString = function () {\n    return signature;\n  };\n\n  function is_promise(result) {\n    if (options.mode) return options.mode === 'promise';\n    return result && result.then;\n  }\n\n  function is_sync(args) {\n    if (options.mode) return options.mode === 'sync';\n    return macro !== fn.async_noop && macro.length !== args.length + 1;\n  }\n\n  function normalise(signature) {\n    return new RegExp(signature).toString();\n  }\n\n  function convert(args, next) {\n    var index = 0;\n    return $(parsed_signature.converters)\n      .collect(function (converter) {\n        return function (callback) {\n          converter.apply(null, args.slice(index, (index += converter.length - 1)).concat(callback));\n        };\n      })\n      .collect_async(function (converter, index, callback) {\n        converter(callback);\n      }, next);\n  }\n\n  event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n\n},{\"./Array\":1,\"./Context\":3,\"./EventBus\":5,\"./RegularExpression\":12,\"./fn\":22}],11:[function(require,module,exports){\n(function (process,global,__dirname){(function (){\n'use strict';\n\nmodule.exports = Platform;\n\nfunction Platform() {\n  function get_container() {\n    /* eslint-disable no-undef */\n    if (is_browser()) return window;\n    if (is_phantom()) return phantom;\n    if (is_node()) return global;\n    /* eslint-enable no-undef */\n  }\n\n  function is_node() {\n    return typeof process !== 'undefined' && typeof global !== 'undefined' && typeof __dirname !== 'undefined';\n  }\n\n  function is_browser() {\n    return typeof window !== 'undefined';\n  }\n\n  function is_phantom() {\n    return typeof phantom !== 'undefined';\n  }\n\n  function is_karma() {\n    return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n  }\n\n  return {\n    get_container: get_container,\n    is_node: is_node,\n    is_browser: is_browser,\n    is_phantom: is_phantom,\n    is_karma: is_karma,\n  };\n}\n\n}).call(this)}).call(this,require('_process'),typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {},\"/lib\")\n},{\"_process\":58}],12:[function(require,module,exports){\n'use strict';\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function (pattern_or_regexp) {\n  var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n  var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n  var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n  var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n  var non_word_tokens_pattern = /[^\\w\\s]/g;\n  var regexp = new RegExp(pattern_or_regexp);\n\n  this.test = function (text) {\n    var result = regexp.test(text);\n    this.reset();\n    return result;\n  };\n\n  this.groups = function (text) {\n    var results = $();\n    var match = regexp.exec(text);\n    while (match) {\n      var groups = match.slice(1, match.length);\n      results.push(groups);\n      match = regexp.global && regexp.exec(text);\n    }\n    this.reset();\n    return results.flatten();\n  };\n\n  this.reset = function () {\n    regexp.lastIndex = 0;\n    return this;\n  };\n\n  this.without_expressions = function () {\n    return regexp.source.replace(groups_pattern, '$1').replace(sets_pattern, '$1').replace(repetitions_pattern, '$1').replace(regex_aliases_pattern, '$1').replace(non_word_tokens_pattern, '');\n  };\n\n  this.equals = function (other) {\n    return this.toString() === other.toString();\n  };\n\n  this.toString = function () {\n    return '/' + regexp.source + '/';\n  };\n};\n\nmodule.exports = RegularExpression;\n\n},{\"./Array\":1}],13:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  trim: function trim(text) {\n    return text.replace(/^\\s+|\\s+$/g, '');\n  },\n  rtrim: function rtrim(text) {\n    return text.replace(/\\s+$/g, '');\n  },\n  isBlank: function isBlank(text) {\n    return /^\\s*$/g.test(text);\n  },\n  isNotBlank: function isNotBlank(text) {\n    return !this.isBlank(text);\n  },\n  indentation: function indentation(text) {\n    var match = /^(\\s*)/.exec(text);\n    return (match && match[0].length) || 0;\n  },\n};\n\n},{}],14:[function(require,module,exports){\n/*jslint node: true */\n'use strict';\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function (libraries, interpreter_context) {\n  if (!(this instanceof Yadda)) {\n    return new Yadda(libraries, interpreter_context);\n  }\n\n  this.interpreter = new Interpreter(libraries);\n\n  this.requires = function (libraries) {\n    this.interpreter.requires(libraries);\n    return this;\n  };\n\n  this.yadda = function (scenario, scenario_context, next) {\n    if (arguments.length === 0) return this;\n    if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n    this.interpreter.validate(scenario);\n    this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n  };\n\n  // Not everyone shares my sense of humour re the recursive api :(\n  // See https://github.com/acuminous/yadda/issues/111\n  this.run = this.yadda;\n\n  this.toString = function () {\n    return 'Yadda 2.2.0 Copyright 2010 Stephen Cresswell';\n  };\n};\n\nmodule.exports = Yadda;\n\n},{\"./Context\":3,\"./Interpreter\":8,\"./fn\":22}],15:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function date_converter(value, next) {\n  var converted = Date.parse(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n  return next(null, new Date(converted));\n};\n\n},{}],16:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function float_converter(value, next) {\n  var converted = parseFloat(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n  return next(null, converted);\n};\n\n},{}],17:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  date: require('./date-converter'),\n  integer: require('./integer-converter'),\n  float: require('./float-converter'),\n  list: require('./list-converter'),\n  table: require('./table-converter'),\n  pass_through: require('./pass-through-converter'),\n};\n\n},{\"./date-converter\":15,\"./float-converter\":16,\"./integer-converter\":18,\"./list-converter\":19,\"./pass-through-converter\":20,\"./table-converter\":21}],18:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function integer_converter(value, next) {\n  var converted = parseInt(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n  return next(null, converted);\n};\n\n},{}],19:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function list_converter(value, next) {\n  return next(null, value.split(/\\n/));\n};\n\n},{}],20:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function pass_through_converter(value, next) {\n  return next(null, value);\n};\n\n},{}],21:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\nmodule.exports = function table_converter(value, next) {\n  var rows = value.split(/\\n/);\n  var headings = parse_headings(rows.shift());\n  var handler = is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n  var table = $();\n\n  try {\n    $(rows).each(handler);\n    next(null, collapse(table));\n  } catch (err) {\n    next(err);\n  }\n\n  function handle_single_line_row(row) {\n    if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n    start_new_row();\n    parse_fields(row);\n  }\n\n  function handle_multiline_row(row) {\n    if (is_horizinal_separator(row)) return start_new_row();\n    parse_fields(row);\n  }\n\n  function parse_headings(row) {\n    return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX))\n      .collect(function (value) {\n        return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n      })\n      .naked();\n  }\n\n  function is_horizinal_separator(row) {\n    return DASH_REGEX.test(row);\n  }\n\n  function start_new_row() {\n    table.push({});\n  }\n\n  function parse_fields(row) {\n    var fields = table.last();\n    $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function (field, index) {\n      var column = headings[index].text;\n      var indentation = headings[index].indentation;\n      var text = StringUtils.rtrim(field.substr(indentation));\n      if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n      fields[column] = (fields[column] || []).concat(text);\n    });\n  }\n\n  function collapse(table) {\n    return table\n      .collect(function (row) {\n        var new_row = {};\n        for (var heading in row) {\n          new_row[heading] = row[heading].join('\\n');\n        }\n        return new_row;\n      })\n      .naked();\n  }\n};\n\n},{\"../Array\":1,\"../StringUtils\":13}],22:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  var slice = Array.prototype.slice;\n\n  function curry(ctx, fn) {\n    var args = slice.call(arguments, 2);\n    return function () {\n      return fn.apply(ctx, args.concat(slice.call(arguments)));\n    };\n  }\n\n  function invoke(fn, ctx, args) {\n    return fn.apply(ctx, args);\n  }\n\n  function is_function(object) {\n    var getType = {};\n    return object && getType.toString.call(object) === '[object Function]';\n  }\n\n  function noop() {}\n\n  function noargs(fn) {\n    return function () {\n      return fn();\n    };\n  }\n\n  function asynchronize(ctx, fn) {\n    return function () {\n      var next = slice.call(arguments, arguments.length - 1)[0];\n      var args = slice.call(arguments, 0, arguments.length - 2);\n      fn.apply(ctx, args);\n      if (next) next();\n    };\n  }\n\n  return {\n    noop: noop,\n    noargs: noargs,\n    async_noop: asynchronize(null, noop),\n    asynchronize: asynchronize,\n    is_function: is_function,\n    curry: curry,\n    invoke: invoke,\n  };\n})();\n\n},{}],23:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature|功能',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\n    examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\n    pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\n    only: '(?:[Oo]nly|仅仅?)',\n    background: '[Bb]ackground|背景|前提',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Chinese', vocabulary);\n})();\n\n},{\"./Language\":28}],24:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n    scenario: '(?:[Ss]cenario|[Gg|eval)',\n    examples: '(?:[Vv]oorbeelden?)',\n    pending: '(?:[Tt]odo|[Mm]oet nog)',\n    only: '(?:[Aa]lleen)',\n    background: '(?:[Aa]chtergrond)',\n    given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n    when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n    then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Dutch', vocabulary);\n})();\n\n},{\"./Language\":28}],25:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n    examples: '(?:[Ee]xamples|[Ww]here)',\n    pending: '(?:[Pp]ending|[Tt]odo)',\n    only: '(?:[Oo]nly)',\n    background: '[Bb]ackground',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('English', vocabulary);\n})();\n\n},{\"./Language\":28}],26:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]onctionnalité)',\n    scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n    examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n    pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n    only: '(?:[Ss]eulement])',\n    background: '(?:[Cc]ontexte)',\n    given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n    when: \"(?:[Qq]uand|[Ll]orsqu'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)\",\n    then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n    _steps: ['given', 'when', 'then', 'soit', 'etantdonnees', 'etantdonnee', 'etantdonne', 'quand', 'lorsque', 'alors'],\n    // Also aliasing French verbs for given-when-then for signature-lookup\n    get soit() {\n      return this.given;\n    },\n    get etantdonnees() {\n      return this.given;\n    },\n    get etantdonnee() {\n      return this.given;\n    },\n    get etantdonne() {\n      return this.given;\n    },\n    get quand() {\n      return this.when;\n    },\n    get lorsque() {\n      return this.when;\n    },\n    get alors() {\n      return this.then;\n    },\n  };\n\n  return new Language('French', vocabulary);\n})();\n\n},{\"./Language\":28}],27:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n    scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n    examples: '(?:[Bb]eispiele?)',\n    pending: '(?:[Tt]odo|[Oo]ffen)',\n    only: '(?:[Nn]ur|[Ee]inzig)',\n    background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n    given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n    when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n    then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('German', vocabulary);\n})();\n\n},{\"./Language\":28}],28:[function(require,module,exports){\n'use strict';\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function (name, vocabulary) {\n  var _this = this;\n\n  // See http://github.com/acuminous/yadda#203\n  this.is_language = true;\n\n  this.library = function (dictionary) {\n    return _this.localise_library(new Library(dictionary));\n  };\n\n  this.localise_library = function (library) {\n    $(vocabulary._steps).each(function (keyword) {\n      library[keyword] = function (signatures, fn, ctx, options) {\n        return $(signatures).each(function (signature) {\n          signature = prefix_signature(_this.localise(keyword), signature);\n          return library.define(signature, fn, ctx, options);\n        });\n      };\n    });\n    return library;\n  };\n\n  var prefix_signature = function (prefix, signature) {\n    var regex_delimiters = new RegExp('^/|/$', 'g');\n    var start_of_signature = new RegExp(/^(?:\\^)?/);\n    var one_or_more_spaces = '\\\\s+';\n    var leading_spaces = '^(?:\\\\s)*';\n    return signature\n      .toString()\n      .replace(regex_delimiters, '')\n      .replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n  };\n\n  this.localise = function (keyword) {\n    if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n    return vocabulary[keyword];\n  };\n};\n\n},{\"../Array\":1,\"../Library\":9}],29:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ee]genskap',\n    scenario: '[Ss]cenario',\n    examples: '[Ee]ksempler',\n    pending: '[Aa]vventer',\n    only: '[Bb]are',\n    background: '[Bb]akgrunn',\n    given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n    when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n    then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n    _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n    // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n    get gitt() {\n      return this.given;\n    },\n    get når() {\n      return this.when;\n    },\n    get så() {\n      return this.then;\n    },\n  };\n\n  return new Language('Norwegian', vocabulary);\n})();\n\n},{\"./Language\":28}],30:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Tt]ale|[Yy]arn)',\n    scenario: '(?:[Aa]dventure|[Ss]ortie)',\n    examples: '[Ww]herest',\n    pending: '[Bb]rig',\n    only: '[Bb]lack [Ss]pot',\n    background: '[Aa]ftground',\n    given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n    // Also aliasing Pirate verbs for given-when-then for signature-lookup\n    get giveth() {\n      return this.given;\n    },\n    get whence() {\n      return this.when;\n    },\n    get thence() {\n      return this.then;\n    },\n  };\n\n  return new Language('Pirate', vocabulary);\n})();\n\n},{\"./Language\":28}],31:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n    scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n    examples: '[Pp]rzykłady',\n    pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n    only: '[Tt]ylko',\n    background: '[Zz]ałożenia',\n    given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n    when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n    then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n    _steps: ['given', 'when', 'then', 'zakladajac', 'majac', 'jezeli', 'jesli', 'gdy', 'kiedy', 'wtedy'],\n    // Also aliasing Polish verbs for given-when-then for signature-lookup\n    get zakladajac() {\n      return this.given;\n    },\n    get majac() {\n      return this.given;\n    },\n    get jezeli() {\n      return this.when;\n    },\n    get jesli() {\n      return this.when;\n    },\n    get gdy() {\n      return this.when;\n    },\n    get kiedy() {\n      return this.when;\n    },\n    get wtedy() {\n      return this.then;\n    },\n  };\n\n  return new Language('Polish', vocabulary);\n})();\n\n},{\"./Language\":28}],32:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n    scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n    examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n    pending: '[Pp]endente',\n    only: '[S][óo]',\n    background: '[Ff]undo',\n    given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n    when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n    then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n    _steps: ['given', 'when', 'then', 'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas', 'quando', 'se', 'entao'],\n\n    get seja() {\n      return this.given;\n    },\n    get sejam() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get quando() {\n      return this.when;\n    },\n    get se() {\n      return this.when;\n    },\n    get entao() {\n      return this.then;\n    },\n  };\n\n  return new Language('Portuguese', vocabulary);\n})();\n\n},{\"./Language\":28}],33:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n    scenario: 'Сценарий',\n    examples: 'Примеры?',\n    pending: '(?:[Ww]ip|[Tt]odo)',\n    only: 'Только',\n    background: '(?:[Пп]редыстория|[Кк]онтекст)',\n    given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Russian', vocabulary);\n})();\n\n},{\"./Language\":28}],34:[function(require,module,exports){\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n    scenario: '(?:[Ee]scenario|[Cc]aso)',\n    examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n    pending: '[Pp]endiente',\n    only: '[S]ólo',\n    background: '[Ff]ondo',\n    given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n    when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n    then: '(?:[Ee]ntonces)',\n\n    _steps: ['given', 'when', 'then', 'sea', 'sean', 'dado', 'dada', 'dados', 'dadas', 'cuando', 'si', 'entonces'],\n\n    get sea() {\n      return this.given;\n    },\n    get sean() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get cuando() {\n      return this.when;\n    },\n    get si() {\n      return this.when;\n    },\n    get entonces() {\n      return this.then;\n    },\n  };\n\n  return new Language('Spanish', vocabulary);\n})();\n\n},{\"./Language\":28}],35:[function(require,module,exports){\n/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n    scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n    examples: '[Пп]риклади',\n    pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n    only: '[Тт]ільки',\n    background: '[Кк]онтекст',\n    given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n    when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n    then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Ukrainian', vocabulary);\n})();\n\n},{\"./Language\":28}],36:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  Chinese: require('./Chinese'),\n  English: require('./English'),\n  French: require('./French'),\n  German: require('./German'),\n  Dutch: require('./Dutch'),\n  Norwegian: require('./Norwegian'),\n  Pirate: require('./Pirate'),\n  Ukrainian: require('./Ukrainian'),\n  Polish: require('./Polish'),\n  Spanish: require('./Spanish'),\n  Russian: require('./Russian'),\n  Portuguese: require('./Portuguese'),\n  default: require('./English'),\n  Language: require('./Language'),\n};\n\n},{\"./Chinese\":23,\"./Dutch\":24,\"./English\":25,\"./French\":26,\"./German\":27,\"./Language\":28,\"./Norwegian\":29,\"./Pirate\":30,\"./Polish\":31,\"./Portuguese\":32,\"./Russian\":33,\"./Spanish\":34,\"./Ukrainian\":35}],37:[function(require,module,exports){\n'use strict';\n\nvar FeatureFileParser = function (options) {\n  var fs = require('../shims').fs;\n  var FeatureParser = require('./FeatureParser');\n  var parser = new FeatureParser(options);\n\n  this.parse = function (file, next) {\n    var text = fs.readFileSync(file, 'utf8');\n    var feature = parser.parse(text);\n    return (next && next(feature)) || feature;\n  };\n};\n\nmodule.exports = FeatureFileParser;\n\n},{\"../shims\":49,\"./FeatureParser\":38}],38:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function (options) {\n  /* eslint-disable no-redeclare */\n  var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']' };\n  var options = options && options.is_language ? { language: options } : options || defaults;\n  var language = options.language || defaults.language;\n  var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n  var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n  /* eslint-enable no-redeclare */\n\n  var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n  var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n  var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n  var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n  var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n  var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n  var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n  var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n  var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n  var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n  var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n  var specification;\n  var comment;\n\n  this.parse = function (text, next) {\n    reset();\n    split(text).each(parse_line);\n    return (next && next(specification.export())) || specification.export();\n  };\n\n  function reset() {\n    specification = new Specification();\n    comment = false;\n  }\n\n  function split(text) {\n    return $(text.split(/\\r\\n|\\n/));\n  }\n\n  function parse_line(line, index) {\n    var match;\n    var line_number = index + 1;\n    try {\n      // eslint-disable-next-line no-return-assign\n      if ((match = MULTI_LINE_COMMENT_REGEX.test(line))) return (comment = !comment);\n      if (comment) return;\n      if ((match = SINGLE_LINE_COMMENT_REGEX.test(line))) return;\n      if ((match = SIMPLE_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n      if ((match = NVP_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n      if ((match = FEATURE_REGEX.exec(line))) return specification.handle('Feature', match[1], line_number);\n      if ((match = SCENARIO_REGEX.exec(line))) return specification.handle('Scenario', match[1], line_number);\n      if ((match = BACKGROUND_REGEX.exec(line))) return specification.handle('Background', match[1], line_number);\n      if ((match = EXAMPLES_REGEX.exec(line))) return specification.handle('Examples', line_number);\n      if ((match = BLANK_REGEX.exec(line))) return specification.handle('Blank', match[0], line_number);\n      if ((match = DASH_REGEX.exec(line))) return specification.handle('Dash', match[1], line_number);\n      if ((match = TEXT_REGEX.exec(line))) return specification.handle('Text', match[1], line_number);\n    } catch (e) {\n      e.message = 'Error parsing line ' + line_number + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n      throw e;\n    }\n  }\n\n  var Handlers = function (handlers) {\n    // eslint-disable-next-line no-redeclare\n    var handlers = handlers || {};\n\n    this.register = function (event, handler) {\n      handlers[event] = handler;\n    };\n\n    this.unregister = function () {\n      $(Array.prototype.slice.call(arguments)).each(function (event) {\n        delete handlers[event];\n      });\n    };\n\n    this.find = function (event) {\n      if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n      return { handle: handlers[event.toLowerCase()] };\n    };\n  };\n\n  var Specification = function () {\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      text: fn.noop,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      feature: start_feature,\n      scenario: start_scenario,\n      background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n      // eslint-disable-next-line no-return-assign\n      return (feature = new Feature(title, annotations, new Annotations()));\n    }\n\n    function start_scenario(event, title, line_number) {\n      feature = new Feature(title, new Annotations(), annotations);\n      return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function (event, data, line_number) {\n      current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      if (!feature) throw new Error('A feature must contain one or more scenarios');\n      return feature.export();\n    };\n  };\n\n  var Annotations = function () {\n    var annotations = {};\n\n    this.stash = function (key, value) {\n      if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n      annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function () {\n      return annotations;\n    };\n  };\n\n  var Feature = function (title, annotations, stashed_annotations) {\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n      text: capture_description,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n      background: start_background,\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n      background = new Background(title, _this);\n      stashed_annotations = new Annotations();\n      return background;\n    }\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background', 'text');\n      stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n      description.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, title) {\n      var scenario = new Scenario(title, background, stashed_annotations, _this);\n      scenarios.push(scenario);\n      stashed_annotations = new Annotations();\n      return scenario;\n    }\n\n    function validate() {\n      if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        scenarios: $(scenarios)\n          .collect(function (scenario) {\n            return scenario.export();\n          })\n          .flatten()\n          .naked(),\n      };\n    };\n  };\n\n  var Background = function (title, feature) {\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n    });\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', stash_annotation);\n      handlers.register('scenario', start_scenario);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      validate();\n      return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        steps: steps,\n      };\n    };\n  };\n\n  var NullBackground = function () {\n    var handlers = new Handlers();\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      return {\n        steps: [],\n      };\n    };\n  };\n\n  var Scenario = function (title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: start_scenario,\n      scenario: start_scenario,\n      examples: start_examples,\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n      handlers.register('examples', start_examples);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n      validate();\n      examples = new Examples(_this);\n      return examples;\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      var result = {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        steps: background.export().steps.concat(steps),\n      };\n      return examples ? examples.expand(result) : result;\n    };\n  };\n\n  var Examples = function (scenario) {\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      blank: fn.noop,\n      dash: start_example_table,\n      text: capture_headings,\n    });\n\n    function start_example_table(evnet, data, line_number) {\n      handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n      handlers.register('annotation', stash_annotation);\n      handlers.register('text', capture_singleline_fields);\n      handlers.register('dash', enable_multiline_examples);\n      var pos = 1;\n      headings = split(data)\n        .collect(function (column) {\n          var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n          pos += column.length + 1;\n          return attributes;\n        })\n        .naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      handlers.unregister('blank', 'dash');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n      handlers.register('dash', end_example_table);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n      annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', continue_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n      parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n      handlers.unregister('text', 'dash');\n      handlers.register('blank', fn.noop);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n      var fields = examples.last().fields;\n      $(headings).each(function (heading) {\n        fields[heading.text + '.index'] = [examples.length];\n        fields[heading.text + '.start.line'] = [line_number];\n        fields[heading.text + '.start.column'] = [heading.left + heading.indentation];\n      });\n    }\n\n    function parse_fields(row, fields) {\n      split(row, headings.length).each(function (field, index) {\n        var column = headings[index].text;\n        var indentation = headings[index].indentation;\n        var text = StringUtils.rtrim(field.substr(indentation));\n        if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n        fields[column] = (fields[column] || []).concat(text);\n      });\n      return fields;\n    }\n\n    function split(row, number_of_fields) {\n      var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n      var fields = $(row.split(separator));\n      if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n        throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n      }\n      return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n      if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function (scenario) {\n      validate();\n      return examples\n        .collect(function (example) {\n          return {\n            title: substitute(example.fields, scenario.title),\n            annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n            description: substitute_all(example, scenario.description),\n            steps: substitute_all(example.fields, scenario.steps),\n          };\n        })\n        .naked();\n    };\n\n    function shallow_merge() {\n      var result = {};\n      $(Array.prototype.slice.call(arguments)).each(function (annotations) {\n        for (var key in annotations) {\n          result[key] = annotations[key];\n        }\n      });\n      return result;\n    }\n\n    function substitute_all(example, lines) {\n      return $(lines)\n        .collect(function (line) {\n          return substitute(example, line);\n        })\n        .naked();\n    }\n\n    function substitute(example, line) {\n      for (var heading in example) {\n        line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n      }\n      return line;\n    }\n  };\n};\n\nmodule.exports = FeatureParser;\n\n},{\"../Array\":1,\"../StringUtils\":13,\"../fn\":22,\"../localisation\":36}],39:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\n\nvar StepParser = function () {\n  var NON_BLANK_REGEX = /[^\\s]/;\n\n  this.parse = function (text, next) {\n    var steps = split(text).find_all(non_blanks);\n    return (next && next(steps)) || steps;\n  };\n\n  var split = function (text) {\n    return $(text.split(/\\n/));\n  };\n\n  var non_blanks = function (text) {\n    return text && NON_BLANK_REGEX.test(text);\n  };\n};\n\nmodule.exports = StepParser;\n\n},{\"../Array\":1}],40:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  StepParser: require('./StepParser'),\n  FeatureParser: require('./FeatureParser'),\n  FeatureFileParser: require('./FeatureFileParser'),\n};\n\n},{\"./FeatureFileParser\":37,\"./FeatureParser\":38,\"./StepParser\":39}],41:[function(require,module,exports){\n(function (global){(function (){\n'use strict';\n\nif (!module.client) {\n  var fs = require('../shims').fs;\n  global.process = global.process || {\n    cwd: function () {\n      return fs.workingDirectory;\n    },\n  };\n}\n\nmodule.exports = function (yadda, casper) {\n  var EventBus = require('yadda').EventBus;\n\n  yadda.interpreter.interpret_step = function (step, ctx, next) {\n    var _this = this;\n    casper.then(function () {\n      casper.test.info(step);\n      EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n      _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    });\n  };\n\n  casper.yadda = function (script, ctx) {\n    if (script === undefined) return this;\n    yadda.run(script, ctx);\n  };\n};\n\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"../shims\":49,\"yadda\":\"yadda\"}],42:[function(require,module,exports){\n'use strict';\n\nmodule.exports = {\n  casper: require('./CasperPlugin'),\n  mocha: {\n    ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n    StepLevelPlugin: require('./mocha/StepLevelPlugin'),\n  },\n  get jasmine() {\n    return this.mocha;\n  },\n};\n\n},{\"./CasperPlugin\":41,\"./mocha/ScenarioLevelPlugin\":44,\"./mocha/StepLevelPlugin\":45}],43:[function(require,module,exports){\n'use strict';\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function (options) {\n  /* jslint shadow: true */\n  var platform = new Platform();\n  var language = options.language || Localisation.default;\n  var parser = options.parser || new FeatureFileParser(options);\n  var container = options.container || platform.get_container();\n\n  function featureFiles(files, iterator) {\n    $(files).each(function (file) {\n      features(parser.parse(file), iterator);\n    });\n  }\n\n  function features(features, iterator) {\n    $(features).each(function (feature) {\n      describe(feature.title, feature, iterator);\n    });\n  }\n\n  function describe(title, subject, iterator) {\n    var _describe = getDescribe(subject.annotations);\n    _describe(title, function () {\n      iterator(subject);\n    });\n  }\n\n  function it_async(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function (done) {\n      iterator(this, subject, done);\n    });\n  }\n\n  function it_sync(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function () {\n      iterator(this, subject);\n    });\n  }\n\n  function getIt(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xit;\n    if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n    return container.it;\n  }\n\n  function getDescribe(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xdescribe;\n    if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n    return container.describe;\n  }\n\n  function has_annotation(annotations, name) {\n    var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n    for (var key in annotations) {\n      if (regexp.test(key)) return true;\n    }\n  }\n\n  return {\n    featureFiles: featureFiles,\n    features: features,\n    describe: describe,\n    it_async: it_async,\n    it_sync: it_sync,\n  };\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"../../localisation\":36,\"../../parsers/FeatureFileParser\":37}],44:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n      itFn(scenario.title, scenario, function (context, scenario, done) {\n        iterator(scenario, done);\n      });\n    });\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],45:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      base_plugin.describe(scenario.title, scenario, iterator);\n    });\n  }\n\n  function steps(steps, iterator) {\n    var abort = false;\n\n    $(steps).each(function (step) {\n      var stepFn = iterator.length === 1 ? step_sync : step_async;\n      stepFn(step, iterator);\n    });\n\n    function step_async(step, iterator) {\n      base_plugin.it_async(step, step, function (context, step, done) {\n        if (abort) {\n          return context.skip ? context.skip() : done();\n        }\n        abort = true;\n        iterator.bind(context)(step, function (err) {\n          if (err) return (done.fail || done)(err);\n          abort = false;\n          done();\n        });\n      });\n    }\n\n    function step_sync(step, iterator) {\n      base_plugin.it_sync(step, step, function (context, step) {\n        if (abort) return context.skip && context.skip();\n        abort = true;\n        iterator.bind(context)(step);\n        abort = false;\n      });\n    }\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n  container.steps = steps;\n};\n\n},{\"../../Array\":1,\"../../Platform\":11,\"./BasePlugin\":43}],46:[function(require,module,exports){\n'use strict';\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function (s1, s2) {\n  this.value;\n  this.type = 'LevenshteinDistanceScore';\n  var distance_table;\n  var _this = this;\n\n  var initialise = function () {\n    var x = s1.length;\n    var y = s2.length;\n\n    distance_table = new Array(x + 1);\n\n    /* eslint-disable no-redeclare */\n    for (var i = 0; i <= x; i++) {\n      distance_table[i] = new Array(y + 1);\n    }\n\n    for (var i = 0; i <= x; i++) {\n      for (var j = 0; j <= y; j++) {\n        distance_table[i][j] = 0;\n      }\n    }\n\n    for (var i = 0; i <= x; i++) {\n      distance_table[i][0] = i;\n    }\n\n    for (var j = 0; j <= y; j++) {\n      distance_table[0][j] = j;\n    }\n    /* eslint-enable no-redeclare */\n  };\n\n  var score = function () {\n    // eslint-disable-next-line no-return-assign\n    if (s1 === s2) return (_this.value = 0);\n\n    for (var j = 0; j < s2.length; j++) {\n      for (var i = 0; i < s1.length; i++) {\n        if (s1[i] === s2[j]) {\n          distance_table[i + 1][j + 1] = distance_table[i][j];\n        } else {\n          var deletion = distance_table[i][j + 1] + 1;\n          var insertion = distance_table[i + 1][j] + 1;\n          var substitution = distance_table[i][j] + 1;\n          distance_table[i + 1][j + 1] = Math.min(substitution, deletion, insertion);\n        }\n      }\n    }\n    _this.value = distance_table[s1.length][s2.length];\n  };\n\n  this.compare = function (other) {\n    return other.value - this.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n\n  initialise();\n  score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n\n},{}],47:[function(require,module,exports){\n'use strict';\n\nvar $ = require('../Array');\n\nvar MultiScore = function (scores) {\n  this.scores = $(scores);\n  this.type = 'MultiScore';\n\n  this.compare = function (other) {\n    for (var i = 0; i < this.scores.length; i++) {\n      var difference = this.scores[i].compare(other.scores[i]);\n      if (difference) return difference;\n    }\n    return 0;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    if (this.type !== other.type) return false;\n    return this.compare(other) === 0;\n  };\n};\n\nmodule.exports = MultiScore;\n\n},{\"../Array\":1}],48:[function(require,module,exports){\n'use strict';\n\nvar SameLibraryScore = function (m1, m2) {\n  this.value = m1.is_sibling(m2) ? 1 : 0;\n  this.type = 'SameLibraryScore';\n\n  this.compare = function (other) {\n    return this.value - other.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n};\n\nmodule.exports = SameLibraryScore;\n\n},{}],49:[function(require,module,exports){\n(function (process){(function (){\n'use strict';\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n  var platform = new Platform();\n\n  var shims = {\n    node: function () {\n      return {\n        fs: require('fs'),\n        path: require('path'),\n        process: process,\n      };\n    },\n    phantom: function () {\n      return {\n        fs: require('./phantom-fs'),\n        path: require('./phantom-path'),\n        process: require('./phantom-process'),\n      };\n    },\n    karma: function () {\n      return {\n        fs: require('./karma-fs'),\n        path: require('./karma-path'),\n        process: require('./karma-process'),\n      };\n    },\n  };\n\n  function get_shim() {\n    if (platform.is_phantom()) return shims.phantom();\n    if (platform.is_browser() && platform.is_karma()) return shims.karma();\n    if (platform.is_node()) return shims.node();\n    return {};\n  }\n\n  return get_shim();\n})();\n\n}).call(this)}).call(this,require('_process'))\n},{\"../Platform\":11,\"./karma-fs\":50,\"./karma-path\":51,\"./karma-process\":52,\"./phantom-fs\":53,\"./phantom-path\":54,\"./phantom-process\":55,\"_process\":58,\"fs\":56,\"path\":57}],50:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var path = require('./karma-path');\n\n  function absolutePath(relativePath) {\n    return path.resolve(path.normalize(relativePath.split('\\\\').join('/')));\n  }\n\n  var KarmaFileSystem = function () {\n    this.registry = new KarmaPathRegistry();\n    this.converter = new KarmaUriPathConverter('/base/', '/');\n    this.reader = new KarmaFileReader(this.converter);\n\n    var servedUris = Object.keys(window.__karma__.files);\n    var servedFiles = this.converter.parseUris(servedUris);\n    servedFiles.forEach(this.registry.addFile, this.registry);\n  };\n  KarmaFileSystem.prototype = {\n    constructor: KarmaFileSystem,\n    workingDirectory: '/',\n    existsSync: function (path) {\n      return this.registry.exists(path);\n    },\n    readdirSync: function (path) {\n      return this.registry.getContent(path);\n    },\n    statSync: function (path) {\n      return {\n        isDirectory: function () {\n          return this.registry.isDirectory(path);\n        }.bind(this),\n      };\n    },\n    readFileSync: function (file, encoding) {\n      if (encoding !== 'utf8') throw new Error('This fs.readFileSync() shim does not support other than utf8 encoding.');\n      if (!this.registry.isFile(file)) throw new Error('File does not exist: ' + file);\n      return this.reader.readFile(file);\n    },\n  };\n\n  var KarmaPathRegistry = function KarmaPathRegistry() {\n    this.paths = {};\n  };\n\n  KarmaPathRegistry.prototype = {\n    constructor: KarmaPathRegistry,\n    addFile: function (file) {\n      file = absolutePath(file);\n      this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n      var parentDirectory = path.dirname(file);\n      this.addDirectory(parentDirectory);\n    },\n    addDirectory: function (directory) {\n      directory = absolutePath(directory);\n      this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n      var parentDirectory = path.dirname(directory);\n      if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n    },\n    isFile: function (file) {\n      file = absolutePath(file);\n      return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n    },\n    isDirectory: function (directory) {\n      directory = absolutePath(directory);\n      return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n    },\n    exists: function (node) {\n      node = absolutePath(node);\n      return this.paths.hasOwnProperty(node);\n    },\n    getContent: function (directory) {\n      if (!this.isDirectory(directory)) throw new Error('Not a directory: ' + directory);\n      directory = absolutePath(directory);\n      return Object.keys(this.paths)\n        .filter(function (node) {\n          if (node === directory) return false;\n          var parentDirectory = path.dirname(node);\n          return parentDirectory === directory;\n        }, this)\n        .map(function (node) {\n          return path.basename(node);\n        });\n    },\n  };\n\n  KarmaPathRegistry.TYPE_FILE = 0;\n  KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n  var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n    this.workingDirectory = workingDirectory;\n    this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n    this.baseUri = baseUri;\n    this.baseUriPattern = this.patternFromBase(baseUri);\n  };\n\n  KarmaUriPathConverter.prototype = {\n    constructor: KarmaUriPathConverter,\n    patternFromBase: function (string, flags) {\n      var pattern = '^' + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n      return new RegExp(pattern, flags);\n    },\n    parseUris: function (uris) {\n      return uris\n        .filter(function (uri) {\n          return this.baseUriPattern.test(uri);\n        }, this)\n        .map(function (uri) {\n          return uri.replace(this.baseUriPattern, this.workingDirectory);\n        }, this);\n    },\n    buildUri: function (file) {\n      file = absolutePath(file);\n      if (!this.workingDirectoryPattern.test(file)) throw new Error('Path is not in working directory: ' + file);\n      return file.replace(this.workingDirectoryPattern, this.baseUri);\n    },\n  };\n\n  var KarmaFileReader = function KarmaFileReader(converter) {\n    this.converter = converter;\n  };\n\n  KarmaFileReader.prototype = {\n    constructor: KarmaFileReader,\n    readFile: function (file) {\n      var uri = this.converter.buildUri(file);\n      // eslint-disable-next-line no-undef\n      var xhr = new XMLHttpRequest();\n      xhr.open('get', uri, false);\n      xhr.send();\n      return xhr.responseText;\n    },\n  };\n\n  return new KarmaFileSystem();\n})();\n\n},{\"./karma-path\":51}],51:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n  }\n\n  if (typeof path.normalize !== 'function' || typeof path.dirname !== 'function') throw new Error('The path module emulation does not contain implementations of required functions.');\n\n  return path;\n})();\n\n},{\"path\":57}],52:[function(require,module,exports){\nmodule.exports = (function () {\n  'use strict';\n\n  var fs = require('./karma-fs');\n  var process = {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n\n},{\"./karma-fs\":50}],53:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n\n  fs.existsSync = fs.existsSync || fs.exists;\n\n  fs.readdirSync =\n    fs.readdirSync ||\n    function (path) {\n      return fs.list(path).filter(function (name) {\n        return name !== '.' && name !== '..';\n      });\n    };\n\n  fs.statSync =\n    fs.statSync ||\n    function (path) {\n      return {\n        isDirectory: function () {\n          return fs.isDirectory(path);\n        },\n      };\n    };\n\n  return fs;\n})();\n\n},{\"fs\":56}],54:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    // meh\n  }\n\n  path.join =\n    path.join ||\n    function () {\n      return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n  path.relative =\n    path.relative ||\n    function (from, to) {\n      return from + fs.separator + to;\n    };\n\n  return path;\n})();\n\n},{\"fs\":56,\"path\":57}],55:[function(require,module,exports){\n'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var process = typeof process !== 'undefined' ? process : {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n\n},{\"fs\":56}],56:[function(require,module,exports){\n\n},{}],57:[function(require,module,exports){\n(function (process){(function (){\n// 'path' module extracted from Node.js v8.11.1 (only the posix part)\n// transplited with Babel\n\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// 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 permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nfunction assertPath(path) {\n  if (typeof path !== 'string') {\n    throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));\n  }\n}\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeStringPosix(path, allowAboveRoot) {\n  var res = '';\n  var lastSegmentLength = 0;\n  var lastSlash = -1;\n  var dots = 0;\n  var code;\n  for (var i = 0; i <= path.length; ++i) {\n    if (i < path.length)\n      code = path.charCodeAt(i);\n    else if (code === 47 /*/*/)\n      break;\n    else\n      code = 47 /*/*/;\n    if (code === 47 /*/*/) {\n      if (lastSlash === i - 1 || dots === 1) {\n        // NOOP\n      } else if (lastSlash !== i - 1 && dots === 2) {\n        if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {\n          if (res.length > 2) {\n            var lastSlashIndex = res.lastIndexOf('/');\n            if (lastSlashIndex !== res.length - 1) {\n              if (lastSlashIndex === -1) {\n                res = '';\n                lastSegmentLength = 0;\n              } else {\n                res = res.slice(0, lastSlashIndex);\n                lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n              }\n              lastSlash = i;\n              dots = 0;\n              continue;\n            }\n          } else if (res.length === 2 || res.length === 1) {\n            res = '';\n            lastSegmentLength = 0;\n            lastSlash = i;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          if (res.length > 0)\n            res += '/..';\n          else\n            res = '..';\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0)\n          res += '/' + path.slice(lastSlash + 1, i);\n        else\n          res = path.slice(lastSlash + 1, i);\n        lastSegmentLength = i - lastSlash - 1;\n      }\n      lastSlash = i;\n      dots = 0;\n    } else if (code === 46 /*.*/ && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\n\nfunction _format(sep, pathObject) {\n  var dir = pathObject.dir || pathObject.root;\n  var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');\n  if (!dir) {\n    return base;\n  }\n  if (dir === pathObject.root) {\n    return dir + base;\n  }\n  return dir + sep + base;\n}\n\nvar posix = {\n  // path.resolve([from ...], to)\n  resolve: function resolve() {\n    var resolvedPath = '';\n    var resolvedAbsolute = false;\n    var cwd;\n\n    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n      var path;\n      if (i >= 0)\n        path = arguments[i];\n      else {\n        if (cwd === undefined)\n          cwd = process.cwd();\n        path = cwd;\n      }\n\n      assertPath(path);\n\n      // Skip empty entries\n      if (path.length === 0) {\n        continue;\n      }\n\n      resolvedPath = path + '/' + resolvedPath;\n      resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    }\n\n    // At this point the path should be resolved to a full absolute path, but\n    // handle relative paths to be safe (might happen when process.cwd() fails)\n\n    // Normalize the path\n    resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);\n\n    if (resolvedAbsolute) {\n      if (resolvedPath.length > 0)\n        return '/' + resolvedPath;\n      else\n        return '/';\n    } else if (resolvedPath.length > 0) {\n      return resolvedPath;\n    } else {\n      return '.';\n    }\n  },\n\n  normalize: function normalize(path) {\n    assertPath(path);\n\n    if (path.length === 0) return '.';\n\n    var isAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;\n\n    // Normalize the path\n    path = normalizeStringPosix(path, !isAbsolute);\n\n    if (path.length === 0 && !isAbsolute) path = '.';\n    if (path.length > 0 && trailingSeparator) path += '/';\n\n    if (isAbsolute) return '/' + path;\n    return path;\n  },\n\n  isAbsolute: function isAbsolute(path) {\n    assertPath(path);\n    return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;\n  },\n\n  join: function join() {\n    if (arguments.length === 0)\n      return '.';\n    var joined;\n    for (var i = 0; i < arguments.length; ++i) {\n      var arg = arguments[i];\n      assertPath(arg);\n      if (arg.length > 0) {\n        if (joined === undefined)\n          joined = arg;\n        else\n          joined += '/' + arg;\n      }\n    }\n    if (joined === undefined)\n      return '.';\n    return posix.normalize(joined);\n  },\n\n  relative: function relative(from, to) {\n    assertPath(from);\n    assertPath(to);\n\n    if (from === to) return '';\n\n    from = posix.resolve(from);\n    to = posix.resolve(to);\n\n    if (from === to) return '';\n\n    // Trim any leading backslashes\n    var fromStart = 1;\n    for (; fromStart < from.length; ++fromStart) {\n      if (from.charCodeAt(fromStart) !== 47 /*/*/)\n        break;\n    }\n    var fromEnd = from.length;\n    var fromLen = fromEnd - fromStart;\n\n    // Trim any leading backslashes\n    var toStart = 1;\n    for (; toStart < to.length; ++toStart) {\n      if (to.charCodeAt(toStart) !== 47 /*/*/)\n        break;\n    }\n    var toEnd = to.length;\n    var toLen = toEnd - toStart;\n\n    // Compare paths to find the longest common path from root\n    var length = fromLen < toLen ? fromLen : toLen;\n    var lastCommonSep = -1;\n    var i = 0;\n    for (; i <= length; ++i) {\n      if (i === length) {\n        if (toLen > length) {\n          if (to.charCodeAt(toStart + i) === 47 /*/*/) {\n            // We get here if `from` is the exact base path for `to`.\n            // For example: from='/foo/bar'; to='/foo/bar/baz'\n            return to.slice(toStart + i + 1);\n          } else if (i === 0) {\n            // We get here if `from` is the root\n            // For example: from='/'; to='/foo'\n            return to.slice(toStart + i);\n          }\n        } else if (fromLen > length) {\n          if (from.charCodeAt(fromStart + i) === 47 /*/*/) {\n            // We get here if `to` is the exact base path for `from`.\n            // For example: from='/foo/bar/baz'; to='/foo/bar'\n            lastCommonSep = i;\n          } else if (i === 0) {\n            // We get here if `to` is the root.\n            // For example: from='/foo'; to='/'\n            lastCommonSep = 0;\n          }\n        }\n        break;\n      }\n      var fromCode = from.charCodeAt(fromStart + i);\n      var toCode = to.charCodeAt(toStart + i);\n      if (fromCode !== toCode)\n        break;\n      else if (fromCode === 47 /*/*/)\n        lastCommonSep = i;\n    }\n\n    var out = '';\n    // Generate the relative path based on the path difference between `to`\n    // and `from`\n    for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n      if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {\n        if (out.length === 0)\n          out += '..';\n        else\n          out += '/..';\n      }\n    }\n\n    // Lastly, append the rest of the destination (`to`) path that comes after\n    // the common path parts\n    if (out.length > 0)\n      return out + to.slice(toStart + lastCommonSep);\n    else {\n      toStart += lastCommonSep;\n      if (to.charCodeAt(toStart) === 47 /*/*/)\n        ++toStart;\n      return to.slice(toStart);\n    }\n  },\n\n  _makeLong: function _makeLong(path) {\n    return path;\n  },\n\n  dirname: function dirname(path) {\n    assertPath(path);\n    if (path.length === 0) return '.';\n    var code = path.charCodeAt(0);\n    var hasRoot = code === 47 /*/*/;\n    var end = -1;\n    var matchedSlash = true;\n    for (var i = path.length - 1; i >= 1; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          if (!matchedSlash) {\n            end = i;\n            break;\n          }\n        } else {\n        // We saw the first non-path separator\n        matchedSlash = false;\n      }\n    }\n\n    if (end === -1) return hasRoot ? '/' : '.';\n    if (hasRoot && end === 1) return '//';\n    return path.slice(0, end);\n  },\n\n  basename: function basename(path, ext) {\n    if (ext !== undefined && typeof ext !== 'string') throw new TypeError('\"ext\" argument must be a string');\n    assertPath(path);\n\n    var start = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i;\n\n    if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n      if (ext.length === path.length && ext === path) return '';\n      var extIdx = ext.length - 1;\n      var firstNonSlashEnd = -1;\n      for (i = path.length - 1; i >= 0; --i) {\n        var code = path.charCodeAt(i);\n        if (code === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else {\n          if (firstNonSlashEnd === -1) {\n            // We saw the first non-path separator, remember this index in case\n            // we need it if the extension ends up not matching\n            matchedSlash = false;\n            firstNonSlashEnd = i + 1;\n          }\n          if (extIdx >= 0) {\n            // Try to match the explicit extension\n            if (code === ext.charCodeAt(extIdx)) {\n              if (--extIdx === -1) {\n                // We matched the extension, so mark this as the end of our path\n                // component\n                end = i;\n              }\n            } else {\n              // Extension does not match, so our result is the entire path\n              // component\n              extIdx = -1;\n              end = firstNonSlashEnd;\n            }\n          }\n        }\n      }\n\n      if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;\n      return path.slice(start, end);\n    } else {\n      for (i = path.length - 1; i >= 0; --i) {\n        if (path.charCodeAt(i) === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else if (end === -1) {\n          // We saw the first non-path separator, mark this as the end of our\n          // path component\n          matchedSlash = false;\n          end = i + 1;\n        }\n      }\n\n      if (end === -1) return '';\n      return path.slice(start, end);\n    }\n  },\n\n  extname: function extname(path) {\n    assertPath(path);\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n    for (var i = path.length - 1; i >= 0; --i) {\n      var code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1)\n            startDot = i;\n          else if (preDotState !== 1)\n            preDotState = 1;\n      } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n        // We saw a non-dot character immediately before the dot\n        preDotState === 0 ||\n        // The (right-most) trimmed path component is exactly '..'\n        preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      return '';\n    }\n    return path.slice(startDot, end);\n  },\n\n  format: function format(pathObject) {\n    if (pathObject === null || typeof pathObject !== 'object') {\n      throw new TypeError('The \"pathObject\" argument must be of type Object. Received type ' + typeof pathObject);\n    }\n    return _format('/', pathObject);\n  },\n\n  parse: function parse(path) {\n    assertPath(path);\n\n    var ret = { root: '', dir: '', base: '', ext: '', name: '' };\n    if (path.length === 0) return ret;\n    var code = path.charCodeAt(0);\n    var isAbsolute = code === 47 /*/*/;\n    var start;\n    if (isAbsolute) {\n      ret.root = '/';\n      start = 1;\n    } else {\n      start = 0;\n    }\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i = path.length - 1;\n\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n\n    // Get non-dir info\n    for (; i >= start; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;\n        } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n    // We saw a non-dot character immediately before the dot\n    preDotState === 0 ||\n    // The (right-most) trimmed path component is exactly '..'\n    preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      if (end !== -1) {\n        if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);\n      }\n    } else {\n      if (startPart === 0 && isAbsolute) {\n        ret.name = path.slice(1, startDot);\n        ret.base = path.slice(1, end);\n      } else {\n        ret.name = path.slice(startPart, startDot);\n        ret.base = path.slice(startPart, end);\n      }\n      ret.ext = path.slice(startDot, end);\n    }\n\n    if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';\n\n    return ret;\n  },\n\n  sep: '/',\n  delimiter: ':',\n  win32: null,\n  posix: null\n};\n\nposix.posix = posix;\n\nmodule.exports = posix;\n\n}).call(this)}).call(this,require('_process'))\n},{\"_process\":58}],58:[function(require,module,exports){\n// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things.  But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals.  It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n    throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n    throw new Error('clearTimeout has not been defined');\n}\n(function () {\n    try {\n        if (typeof setTimeout === 'function') {\n            cachedSetTimeout = setTimeout;\n        } else {\n            cachedSetTimeout = defaultSetTimout;\n        }\n    } catch (e) {\n        cachedSetTimeout = defaultSetTimout;\n    }\n    try {\n        if (typeof clearTimeout === 'function') {\n            cachedClearTimeout = clearTimeout;\n        } else {\n            cachedClearTimeout = defaultClearTimeout;\n        }\n    } catch (e) {\n        cachedClearTimeout = defaultClearTimeout;\n    }\n} ())\nfunction runTimeout(fun) {\n    if (cachedSetTimeout === setTimeout) {\n        //normal enviroments in sane situations\n        return setTimeout(fun, 0);\n    }\n    // if setTimeout wasn't available but was latter defined\n    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n        cachedSetTimeout = setTimeout;\n        return setTimeout(fun, 0);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedSetTimeout(fun, 0);\n    } catch(e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n            return cachedSetTimeout.call(null, fun, 0);\n        } catch(e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n            return cachedSetTimeout.call(this, fun, 0);\n        }\n    }\n\n\n}\nfunction runClearTimeout(marker) {\n    if (cachedClearTimeout === clearTimeout) {\n        //normal enviroments in sane situations\n        return clearTimeout(marker);\n    }\n    // if clearTimeout wasn't available but was latter defined\n    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n        cachedClearTimeout = clearTimeout;\n        return clearTimeout(marker);\n    }\n    try {\n        // when when somebody has screwed with setTimeout but no I.E. maddness\n        return cachedClearTimeout(marker);\n    } catch (e){\n        try {\n            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally\n            return cachedClearTimeout.call(null, marker);\n        } catch (e){\n            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n            // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n            return cachedClearTimeout.call(this, marker);\n        }\n    }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n    if (!draining || !currentQueue) {\n        return;\n    }\n    draining = false;\n    if (currentQueue.length) {\n        queue = currentQueue.concat(queue);\n    } else {\n        queueIndex = -1;\n    }\n    if (queue.length) {\n        drainQueue();\n    }\n}\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    var timeout = runTimeout(cleanUpNextTick);\n    draining = true;\n\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        while (++queueIndex < len) {\n            if (currentQueue) {\n                currentQueue[queueIndex].run();\n            }\n        }\n        queueIndex = -1;\n        len = queue.length;\n    }\n    currentQueue = null;\n    draining = false;\n    runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n    var args = new Array(arguments.length - 1);\n    if (arguments.length > 1) {\n        for (var i = 1; i < arguments.length; i++) {\n            args[i - 1] = arguments[i];\n        }\n    }\n    queue.push(new Item(fun, args));\n    if (queue.length === 1 && !draining) {\n        runTimeout(drainQueue);\n    }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n    this.fun = fun;\n    this.array = array;\n}\nItem.prototype.run = function () {\n    this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],\"yadda\":[function(require,module,exports){\n'use strict';\n\nvar api = {\n  Yadda: require('./Yadda'),\n  EventBus: require('./EventBus'),\n  Interpreter: require('./Interpreter'),\n  Context: require('./Context'),\n  Library: require('./Library'),\n  Dictionary: require('./Dictionary'),\n  FeatureFileSearch: require('./FeatureFileSearch'),\n  FileSearch: require('./FileSearch'),\n  Platform: require('./Platform'),\n  localisation: require('./localisation/index'),\n  converters: require('./converters/index'),\n  parsers: require('./parsers/index'),\n  plugins: require('./plugins/index'),\n  shims: require('./shims/index'),\n  createInstance: function () {\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n  },\n};\n\nmodule.exports = api;\n\n},{\"./Context\":3,\"./Dictionary\":4,\"./EventBus\":5,\"./FeatureFileSearch\":6,\"./FileSearch\":7,\"./Interpreter\":8,\"./Library\":9,\"./Platform\":11,\"./Yadda\":14,\"./converters/index\":17,\"./localisation/index\":36,\"./parsers/index\":40,\"./plugins/index\":42,\"./shims/index\":49}]},{},[\"yadda\"]);\n"
  },
  {
    "path": "examples/basic/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/basic\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/basic/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode demo.js\nendlocal"
  },
  {
    "path": "examples/basic/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/basic/bin/example.sh",
    "content": "#!/bin/bash\n\nnode demo.js"
  },
  {
    "path": "examples/basic/demo.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar library = require('./lib/bottles-library');\n\nnew Yadda.createInstance(library).run(['Given 100 green bottles are standing on the wall', 'when 1 green bottle accidentally falls', 'then there are 99 green bottles standing on the wall']);\n"
  },
  {
    "path": "examples/basic/lib/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n\n  var library = English.library()\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles) {\n      wall = new Wall(number_of_bottles);\n      wall.printStatus();\n    })\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles) {\n      wall.fall(number_of_falling_bottles);\n      console.log('%s bottle falls', number_of_falling_bottles);\n    })\n    .then('there are $NUM green bottles standing on the wall', function (number_of_bottles) {\n      assert.equal(number_of_bottles, wall.bottles);\n      wall.printStatus();\n    });\n\n  function Wall(bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n    this.printStatus = function () {\n      console.log('There are %s bottles on the wall', this.bottles);\n    };\n  }\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/basic/package.json",
    "content": "{\n  \"name\": \"yadda-basic-example\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/basic-async/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/basic-async\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/basic-async/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode demo.js\nendlocal"
  },
  {
    "path": "examples/basic-async/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/basic-async/bin/example.sh",
    "content": "#!/bin/bash\n\nnode demo.js"
  },
  {
    "path": "examples/basic-async/demo.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar library = require('./lib/bottles-library');\n\nnew Yadda.createInstance(library).run(['Given 100 green bottles are standing on the wall', 'when 1 green bottle accidentally falls', 'then there are 99 green bottles standing on the wall'], function (err) {\n  if (err) throw err;\n});\n"
  },
  {
    "path": "examples/basic-async/lib/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar assert = require('assert');\nvar format = require('util').format;\n\nmodule.exports = (function () {\n  var wall;\n\n  var library = English.library()\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall = new Wall(number_of_bottles);\n      wall.printStatus();\n      next();\n    })\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      wall.fall(number_of_falling_bottles);\n      console.log('%s bottle falls', number_of_falling_bottles);\n      next();\n    })\n    .then('there are $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      if (number_of_bottles != wall.bottles) return next(new Error(format('Expected %d but got %d', number_of_bottles, wall.bottles)));\n      wall.printStatus();\n      next();\n    });\n\n  function Wall(bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n    this.printStatus = function () {\n      console.log('There are %s bottles on the wall', this.bottles);\n    };\n  }\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/basic-async/package.json",
    "content": "{\n  \"name\": \"yadda-basic-async-example\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/context/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/context\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/context/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/context/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/context/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/context/features/context.feature",
    "content": "Feature: Shared Context\n\nScenario: Sharing context between libraries\n\n    Fred is a patient at Middleton hospital.\n    He was admitted to the respiratory ward with breathing difficulty two days ago.\n    His condition has improved sufficiently for him to be scheduled for discharge tomorrow at 10:00.\n    He requires a taxi and some oxygen.\n    His chart should reflect all of the above\n\n\n\n\n"
  },
  {
    "path": "examples/context/lib/discharge-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000;\n\n  var library = new Yadda.Library()\n\n    .define('His condition has improved sufficiently for him to be scheduled for discharge (today|tomorrow) at $time.', function (day, time, next) {\n      var patient = this.ctx.patient;\n      var timestamp = toTime(day, time);\n      patient.ward.scheduleDischarge(patient, timestamp);\n      next();\n    })\n\n    .define(\n      ['He requires a $requirement', 'He requires a $requirement and some $requirement.'],\n      function () {\n        var next = Array.prototype.pop.apply(arguments);\n        var requirements = Array.prototype.slice.apply(arguments);\n        var patient = this.ctx.patient;\n        patient.discharge.requirements = requirements;\n        next();\n      },\n      {},\n      { mode: 'async' }\n    );\n\n  function toTime(day, time) {\n    var offset = day == 'today' ? 0 : ONE_DAY_IN_MILLIS;\n    return Date.parse(new Date().toString().replace(/\\d{2}:\\d{2}:\\d{2}/, time + ':00')) + offset;\n  }\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/context/lib/hospital-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000;\n\n  var dictionary = new Yadda.Dictionary().define('NUM', /(\\d+)/);\n\n  var library = new Yadda.Library(dictionary).define('He was admitted to the $speciality ward with $complaint $num days ago.', function (speciality, complaint, daysAgo, next) {\n    var patient = this.ctx.patient;\n    patient.speciality = speciality;\n    patient.complaint = complaint;\n    var hospital = this.ctx.hospital;\n    var ward = hospital.getWard(speciality);\n    var admission = new Date().getTime() - ONE_DAY_IN_MILLIS * 2;\n    var bed = ward.admit(patient, admission);\n    next();\n  });\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/context/lib/patient-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var gender = {\n    Fred: 'M',\n    Sue: 'F',\n  };\n\n  var library = new Yadda.Library()\n\n    .define('$patientName is a patient at $hospitalName hospital.', function (patientName, hospitalName, next) {\n      this.ctx.patient = {\n        name: patientName,\n        gender: gender[patientName],\n        chart: function () {\n          return {\n            name: this.name,\n            gender: this.gender,\n            speciality: this.speciality,\n            complaint: this.complaint,\n            admission: this.admission,\n            discharge: {\n              time: this.discharge.time,\n              requirements: this.discharge.requirements,\n            },\n          };\n        },\n      };\n      this.ctx.hospital = this.ctx.hospitals[hospitalName];\n      next();\n    })\n\n    .define('His chart should reflect all of the above', function (next) {\n      var patient = this.ctx.patient;\n      var chart = patient.chart();\n      assert.equal(chart.name, patient.name);\n      assert.equal(chart.gender, patient.gender);\n      assert.equal(chart.speciality, patient.speciality);\n      assert.equal(chart.complaint, patient.complaint);\n      assert.equal(chart.admission, patient.admission);\n      assert.equal(chart.discharge.time, patient.discharge.time);\n      assert.deepEqual(chart.discharge.requirements.toString(), patient.discharge.requirements.toString());\n      next();\n    });\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/context/package.json",
    "content": "{\n  \"name\": \"yadda-context-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/context/test.js",
    "content": "/* jslint node: true */\n/* global mocha, featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  var MiddletonHospital = {\n    getWard: function (speciality) {\n      return this.wards[speciality];\n    },\n    wards: {\n      respiratory: {\n        admit: function (patient, timestamp) {\n          patient.ward = this;\n          patient.admission = timestamp;\n        },\n        scheduleDischarge: function (patient, timestamp) {\n          patient.discharge = { time: timestamp };\n        },\n      },\n    },\n  };\n\n  featureFile(file, function (feature) {\n    var libraries = [require('./lib/hospital-library'), require('./lib/patient-library'), require('./lib/discharge-library')];\n\n    var yadda = Yadda.createInstance(libraries);\n\n    scenarios(feature.scenarios, function (scenario) {\n      var ctx = { hospitals: { Middleton: MiddletonHospital } };\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, { ctx: ctx }, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/data-tables/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/data-tables/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/data-tables/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/data-tables/features/data-tables.feature",
    "content": "Scenario: List\n\n    Given a list of integers\n    ----\n    1000\n    2022\n    9405\n    ----\n\n    Then the total should be 12427\n\n\nScenario: Simple Table\n\n    Given a table of data\n\n    ------------\n    left | right\n    1    | 3\n    2    | 4\n    ------------\n\n    Then the left total should be 3\n    And the right total should be 7\n\n\n@Pending\nScenario: Multiline Table\n\n    Given some Shakespeare\n\n    -----------------------------------------------------\n    Henry V                     | Romeo and Juliet\n    ----------------------------|------------------------\n    Once more unto the          | What light from yonder\n    breech dear friends         | window breaks\n    ----------------------------|------------------------\n    And sheathed their          | It is the East\n    swords for lack of argument | and Juliet is the sun\n    -----------------------------------------------------\n\n    Then the Henry V extract should have 14 words\n    And the Romeo and Juliet extract should have 15 words"
  },
  {
    "path": "examples/data-tables/library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var list_total;\n  var table_totals;\n\n  var dictionary = new Dictionary()\n    .define('totals', /(\\d+)/, Yadda.converters.integer)\n    .define('list', /([^\\u0000]*)/, Yadda.converters.list)\n    .define('table', /([^\\u0000]*)/, Yadda.converters.table);\n\n  var library = English.library(dictionary)\n\n    .given('a list of integers\\n$list', function (list) {\n      list_total = 0;\n      for (var i = 0; i < list.length; i++) {\n        list_total += parseInt(list[i]);\n      }\n    })\n\n    .then('the total should be $total', function (expected) {\n      assert.equal(list_total, expected);\n    })\n\n    .given('a table of data\\n$table', function (table) {\n      table_totals = { left: 0, right: 0 };\n      for (var i = 0; i < table.length; i++) {\n        table_totals.left += parseInt(table[i].left);\n        table_totals.right += parseInt(table[i].right);\n      }\n    })\n\n    .then('the $key total should be $total', function (key, expected) {\n      assert.equal(table_totals[key], expected);\n    })\n\n    .given('some Shakespeare\\n$table', function (table) {\n      table_totals = { 'Henry V': 0, 'Romeo and Juliet': 0 };\n      for (var i = 0; i < table.length; i++) {\n        table_totals['Henry V'] += table['Henry V'].split(/\\s/).length;\n        table_totals['Romeo and Juliet'] += table['Romeo and Juliet'].split(/\\s/).length;\n      }\n    })\n\n    .then('the $extract extract should have $total words', function (extract, expected) {\n      assert.equal(extract.split(/\\W/).length, expected);\n    });\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/data-tables/package.json",
    "content": "{\n  \"name\": \"data-tables\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Yadda multiline examples sample\",\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"license\": \"Apache2\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  }\n}\n"
  },
  {
    "path": "examples/data-tables/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./library');\n\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step) {\n        yadda.run(step);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/dictionary/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/dictionary\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/dictionary/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/dictionary/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/dictionary/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/dictionary/dictionary-library.js",
    "content": "/* jslint node: true */\n'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar converters = Yadda.converters;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var dictionary = new Dictionary()\n    .define('integer', /(\\d+)/, converters.integer)\n    .define('float', /(\\d+.\\d+)/, converters.float)\n    .define('date', /(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z)/, converters.date)\n    .define('period', /(\\d+) (days|months|years)/, function (quantity, units, cb) {\n      cb(null, { quantity: parseInt(quantity), units: units });\n    });\n  var library = English.library(dictionary)\n\n    .define('Expect $integer to be an integer', function (i, next) {\n      assert.equal(typeof i, 'number');\n      assert(i % 1 === 0);\n      next();\n    })\n\n    .define('Expect $float to be a float', function (f, next) {\n      assert.equal(typeof f, 'number');\n      assert(f % 1 !== 0);\n      next();\n    })\n\n    .define('Expect $date to be a date', function (d, next) {\n      assert.equal(Object.prototype.toString.call(d), '[object Date]');\n      next();\n    })\n\n    .define('Expect $period to have a quantity of $integer and units of $units', function (period, quantity, units, next) {\n      assert.equal(period.quantity, quantity);\n      assert.equal(period.units, units);\n      next();\n    });\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/dictionary/features/dictionary.feature",
    "content": "Feature: Dictionary Example\n\nScenario: Argument Converters\n\n    Expect 1 to be an integer\n    Expect 1.1 to be a float\n    Expect 1974-07-15T16:03:21Z to be a date\n    Expect 3 days to have a quantity of 3 and units of days\n\n"
  },
  {
    "path": "examples/dictionary/package.json",
    "content": "{\n  \"name\": \"yadda-dictionary-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/dictionary/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./dictionary-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/jasmine/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/jasmine\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/jasmine/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\jasmine spec\\bottles-spec.js\nendlocal\n"
  },
  {
    "path": "examples/jasmine/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/jasmine/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/jasmine spec/bottles-spec.js\n"
  },
  {
    "path": "examples/jasmine/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n\n  var library = English.library(dictionary)\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall = new Wall(number_of_bottles);\n      next();\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      wall.fall(number_of_falling_bottles);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      assert.equal(number_of_bottles, wall.bottles);\n      next();\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/jasmine/features/bottles.feature",
    "content": "@Only\nFeature: Jasmine Example\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Pending\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n"
  },
  {
    "path": "examples/jasmine/package.json",
    "content": "{\n  \"name\": \"yadda-jasmine-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"jasmine\": \"^2.99.0\",\n    \"jasmine-spec-reporter\": \"^4.2.1\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/jasmine/spec/bottles-spec.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps, jasmine */\n'use strict';\n\nvar SpecReporter = require('jasmine-spec-reporter').SpecReporter;\njasmine.getEnv().addReporter(new SpecReporter());\n\nvar Yadda = require('yadda');\nYadda.plugins.jasmine.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('../bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/jasmine/spec/support/jasmine.json",
    "content": "{\n  \"spec_dir\": \"spec\",\n  \"spec_files\": [\"**/*[sS]pec.js\"],\n  \"helpers\": [\"helpers/**/*.js\"]\n}\n"
  },
  {
    "path": "examples/localisation/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/localisation\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/localisation/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/localisation/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/localisation/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/localisation/bottles-library.js",
    "content": "'use strict';\n\nvar Pirate = require('../../lib/localisation/Pirate');\nvar Dictionary = require('../../lib/Dictionary');\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n\n  var library = Pirate.library(dictionary)\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall = new Wall(number_of_bottles);\n      next();\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      wall.fall(number_of_falling_bottles);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      assert.equal(number_of_bottles, wall.bottles);\n      next();\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/localisation/features/bottles.feature",
    "content": "Yarn: Pirate Example\n\nAdventure: A bottle falls from the wall\n\n    Giveth 100 green bottles are standing on the wall\n    whence 1 green bottle accidentally falls\n    thence there are 99 green bottles standing on the wall\n\nSortie: No bottles are left\n\n    Giveth 1 green bottles are standing on the wall\n    whence 1 green bottle accidentally falls\n    thence there are 0 green bottles standing on the wall\n\n@Brig\nAdventure: Bottles are reset\n\n    Giveth there are no green bottles\n    whence 5 minutes has elapsed\n    thence there are 100 green bottles standing on the wall\n\nAdventure: [N] bottles are standing on a wall\n\n    Giveth [N] green bottles are standing on the wall\n    whence 1 green bottle accidentally falls\n    thence there are [N-1] green bottles standing on the wall\n\n    Wherest:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/localisation/package.json",
    "content": "{\n  \"name\": \"yadda-localisation-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/localisation/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.localisation.default = Yadda.localisation.Pirate;\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/mocha-async/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/mocha-async\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/mocha-async/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/mocha-async/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/mocha-async/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/mocha-async/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n  var library = English.library(dictionary)\n\n    .given('a $NUM foot wall', function (height, next) {\n      wall = new Wall();\n      next();\n    })\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall.bottles = number_of_bottles;\n      next();\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      wall.fall(number_of_falling_bottles);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      assert.equal(number_of_bottles, wall.bottles);\n      next();\n    })\n\n    .then('this test should be skipped', function () {\n      this.mocha.skip();\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-async/features/bottles.feature",
    "content": "Feature: Mocha Asynchronous Example\n\nBackground:\n\n    Given a 6 foot wall\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Todo\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n\nScenario: [N] bottles are standing on a wall\n\n    Given [N] green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are [N-1] green bottles standing on the wall\n    and this test should be skipped\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/mocha-async/package.json",
    "content": "{\n  \"name\": \"yadda-mocha-async-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/mocha-async/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, { mocha: this }, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/mocha-async-slp/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/mocha-async\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/mocha-async-slp/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/mocha-async-slp/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/mocha-async-slp/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/mocha-async-slp/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n  var library = English.library(dictionary)\n\n    .given('a $NUM foot wall', function (height, next) {\n      wall = new Wall();\n      next();\n    })\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall.bottles = number_of_bottles;\n      next();\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      wall.fall(number_of_falling_bottles);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      assert.equal(number_of_bottles, wall.bottles);\n      next();\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-async-slp/features/bottles.feature",
    "content": "Feature: Mocha Asynchronous Example\n\nBackground:\n\n    Given a 6 foot wall\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Todo\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n\nScenario: [N] bottles are standing on a wall\n\n    Given [N] green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are [N-1] green bottles standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/mocha-async-slp/package.json",
    "content": "{\n  \"name\": \"yadda-mocha-async-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/mocha-async-slp/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.ScenarioLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario, done) {\n      yadda.run(scenario.steps, done);\n    });\n  });\n});\n"
  },
  {
    "path": "examples/mocha-async-thenable/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/mocha-async-thenable\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/mocha-async-thenable/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/mocha-async-thenable/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/mocha-async-thenable/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/mocha-async-thenable/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n  var library = English.library(dictionary)\n\n    .given('a $NUM foot wall', function (height) {\n      return new Promise(function (resolve, reject) {\n        setTimeout(function () {\n          wall = new Wall();\n          resolve(true);\n        }, 100);\n      });\n    })\n\n    .given('$NUM green $ITEMS are standing on the wall', function (number_of_items, item_type) {\n      return new Promise(function (resolve, reject) {\n        setTimeout(function () {\n          wall.items = number_of_items;\n          resolve(true);\n        }, 100);\n      });\n    })\n\n    .when('$NUM green $ITEM accidentally falls', function (number_of_falling_items, item_type) {\n      return new Promise(function (resolve, reject) {\n        setTimeout(function () {\n          wall.fall(number_of_falling_items);\n          resolve(true);\n        }, 100);\n      });\n    })\n\n    .then('there (?:are|are still) $NUM green $ITEMS standing on the wall', function (number_of_items, item_type) {\n      return new Promise(function (resolve, reject) {\n        assert.equal(number_of_items, wall.items);\n        resolve(true);\n      });\n    });\n\n  var Wall = function (items) {\n    this.items = items;\n    this.fall = function (n) {\n      this.items -= n;\n    };\n    this.returned = function () {\n      this.items++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-async-thenable/features/bottles.feature",
    "content": "Feature: Mocha Asynchronous Thenable Example Using Bottles\n\nBackground:\n\n    Given a 6 foot wall\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Todo\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n\nScenario: [N] bottles are standing on a wall\n\n    Given [N] green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are [N-1] green bottles standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/mocha-async-thenable/features/cups.feature",
    "content": "Feature: Mocha Asynchronous Thenable Example Using Cups\n\nBackground:\n\n    Given a 6 foot wall\n\nScenario: A cup falls from the wall\n\n    Given 100 green cups are standing on the wall\n    when 1 green cup accidentally falls\n    then there are 99 green cups standing on the wall\n\nScenario: No cups are left\n\n    Given 1 green cups are standing on the wall\n    when 1 green cup accidentally falls\n    then there are 0 green cups standing on the wall\n\n@Todo\nScenario: Bottles are reset\n\n    Given there are no green cups\n    when 5 minutes has elapsed\n    then there are 100 green cups standing on the wall\n\nScenario: [N] cups are standing on a wall\n\n    Given [N] green cups are standing on the wall\n    when 1 green cup accidentally falls\n    then there are [N-1] green cups standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/mocha-async-thenable/package.json",
    "content": "{\n  \"name\": \"yadda-mocha-async-thenable-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Chris Nesbitt-Smith\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/mocha-async-thenable/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/mocha-express/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/mocha-express\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/mocha-express/app.js",
    "content": "'use strict';\n\nvar bodyParser = require('body-parser');\nvar express = require('express');\nvar app = express();\nvar routes = ['./routes/server', './routes/bottles'];\n\nmodule.exports = (function () {\n  var server;\n\n  app.use(bodyParser());\n\n  routes.forEach(function (route) {\n    require(route).init(app);\n  });\n\n  function start(host, port, next) {\n    server = app.listen(port, host, function () {\n      app.on('shutdown_request', stop);\n      app.set('started', new Date());\n      next && next();\n    });\n  }\n\n  function stop(next) {\n    server && server.close(next);\n  }\n\n  return {\n    start: start,\n    stop: stop,\n  };\n})();\n"
  },
  {
    "path": "examples/mocha-express/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test\\test.js\nendlocal"
  },
  {
    "path": "examples/mocha-express/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/mocha-express/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test/test.js"
  },
  {
    "path": "examples/mocha-express/index.js",
    "content": "'use strict';\n\nrequire('./app').start('localhost', 3000);\n"
  },
  {
    "path": "examples/mocha-express/package.json",
    "content": "{\n  \"name\": \"yadda-mocha-express-example\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\",\n    \"start\": \"node index.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache 2\",\n  \"dependencies\": {\n    \"async\": \"~0.2.10\",\n    \"body-parser\": \"^1.18.3\",\n    \"express\": \"^4.16.3\",\n    \"mocha\": \"^5.2.0\",\n    \"node-uuid\": \"~1.4.1\",\n    \"request\": \"^2.88.0\",\n    \"underscore\": \"~1.6.0\"\n  }\n}\n"
  },
  {
    "path": "examples/mocha-express/routes/bottles.js",
    "content": "'use strict';\n\nvar _ = require('underscore');\nvar uuid = require('node-uuid');\n\nmodule.exports = (function () {\n  var bottles = {};\n\n  function init(app) {\n    app.put('/api/bottles', updateBottles);\n    app.get('/api/bottles', listBottles);\n    app.delete('/api/bottles/:id', deleteBottle);\n  }\n\n  function updateBottles(req, res) {\n    bottles = _.chain(req.body).map(toBottles).indexBy('id').value();\n    res.json(_.map(bottles, toJson));\n  }\n\n  function listBottles(req, res) {\n    res.json(_.chain(bottles).filter(byQueryParameters(req)).map(toJson).value());\n  }\n\n  function deleteBottle(req, res) {\n    delete bottles[req.params.id];\n    res.send(204);\n  }\n\n  function toBottles(json) {\n    return _.extend(json, { id: uuid.v1() });\n  }\n\n  function toJson(bottle) {\n    return _.chain(bottle)\n      .clone()\n      .extend({ uri: '/api/bottles/' + bottle.id })\n      .omit('id')\n      .value();\n  }\n\n  function byQueryParameters(req) {\n    return _.matches(req.query);\n  }\n\n  return {\n    init: init,\n  };\n})();\n"
  },
  {
    "path": "examples/mocha-express/routes/server.js",
    "content": "'use strict';\n\nvar events = require('events');\n\nmodule.exports = (function () {\n  function init(app) {\n    app.get('/api/server', status);\n    app.delete('/api/server', shutdown);\n  }\n\n  function status(req, res) {\n    res.send({ started: req.app.get('started') });\n  }\n\n  function shutdown(req, res) {\n    res.send(202);\n    req.app.emit('shutdown_request');\n  }\n\n  return {\n    init: init,\n  };\n})();\n"
  },
  {
    "path": "examples/mocha-express/test/features/bottles.feature",
    "content": "Feature: Mocha Express Example\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Pending\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n\nScenario: [N] bottles are standing on a wall\n\n    Given [N] green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are [N-1] green bottles standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9"
  },
  {
    "path": "examples/mocha-express/test/steps/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\nvar request = require('request');\nvar _ = require('underscore');\nvar async = require('async');\nvar url = require('url');\n\nmodule.exports = (function () {\n  var bottles;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n  var library = English.library(dictionary)\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      var data = _.chain(number_of_bottles)\n        .range()\n        .map(function (data) {\n          return { colour: 'green' };\n        })\n        .value();\n\n      request.put({ url: url.resolve(this.baseUrl, '/api/bottles'), json: data }, function (err, response, body) {\n        assert.ifError(err);\n        assert.equal(response.statusCode, 200);\n        bottles = body;\n        next();\n      });\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      var _this = this;\n      var urls = _.chain(number_of_falling_bottles)\n        .range()\n        .map(function () {\n          return url.resolve(_this.baseUrl, bottles.pop().uri);\n        })\n        .value();\n      async.each(\n        urls,\n        function (url, callback) {\n          request.del(url, function (err, response, body) {\n            assert.ifError(err);\n            assert.equal(response.statusCode, 204);\n            callback();\n          });\n        },\n        next\n      );\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      request.get({ url: url.resolve(this.baseUrl, '/api/bottles'), json: true }, function (err, response, body) {\n        assert.ifError(err);\n        assert.equal(response.statusCode, 200);\n        assert.equal(body.length, parseInt(number_of_bottles));\n        next(err);\n      });\n    });\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-express/test/test.js",
    "content": "/* jslint node: true */\n/* global before, after, featureFile, scenarios, steps */\n'use strict';\n\nvar url = require('url');\nvar request = require('request');\nvar app = require('../app');\nvar assert = require('assert');\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nvar hostname = 'localhost';\nvar port = 3000;\nvar baseUrl = url.format({ protocol: 'http', hostname: hostname, port: port });\nvar serverUrl = url.resolve(baseUrl, '/api/server');\n\nbefore(function (next) {\n  // Stop the application in case it's already running\n  request.del({ url: serverUrl }, function (err, response, body) {\n    app.start(hostname, port, function () {\n      request.get({ url: serverUrl }, function (err, response, body) {\n        assert.ifError(err);\n        assert.equal(response.statusCode, 200);\n        next();\n      });\n    });\n  });\n});\n\nafter(function (next) {\n  app.stop(next);\n});\n\nnew Yadda.FeatureFileSearch('test/features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./steps/bottles-library');\n    var yadda = Yadda.createInstance(library, { baseUrl: baseUrl });\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/mocha-mixed-async-sync/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/mocha-mixed-async-sync\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/mocha-mixed-async-sync/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/mocha-mixed-async-sync/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/mocha-mixed-async-sync/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/mocha-mixed-async-sync/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n  var library = English.library(dictionary)\n\n    .given('a $NUM foot wall', function (height, next) {\n      wall = new Wall();\n      next();\n    })\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall.bottles = number_of_bottles;\n      next();\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles) {\n      wall.fall(number_of_falling_bottles);\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      assert.equal(number_of_bottles, wall.bottles);\n      next();\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-mixed-async-sync/features/bottles.feature",
    "content": "Feature: Mocha Mixed Asynchronous and Synchronous Example\n\nBackground:\n\n    Given a 6 foot wall\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Todo\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n\nScenario: [N] bottles are standing on a wall\n\n    Given [N] green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are [N-1] green bottles standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/mocha-mixed-async-sync/package.json",
    "content": "{\n  \"name\": \"yadda-mocha-mixed-async-sync-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Chris Nesbitt-Smith\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/mocha-mixed-async-sync/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/mocha-multi-library/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/mocha-multi-library\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/mocha-multi-library/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/mocha-multi-library/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/mocha-multi-library/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/mocha-multi-library/features/bottles.feature",
    "content": "@libraries=bottle, common\nFeature: Multi Library Example - Bottles\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Pending\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n\nScenario: [N] bottles are standing on a wall\n\n    Given [N] green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are [N-1] green bottles standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/mocha-multi-library/features/vases.feature",
    "content": "@libraries=vase, common\nFeature: Multi Library Example - Vases\n\nScenario: A vase falls from the wall\n\n    Given 100 green vases are standing on the wall\n    when 1 green vase accidentally falls\n    then there are 99 green vases standing on the wall\n\nScenario: No vases are left\n\n    Given 1 green vases are standing on the wall\n    when 1 green vase accidentally falls\n    then there are 0 green vases standing on the wall\n\n@Pending\nScenario: Bottles are reset\n\n    Given there are no green vases\n    when 5 minutes has elapsed\n    then there are 100 green vases standing on the wall\n\nScenario: [N] vases are standing on a wall\n\n    Given [N] green vases are standing on the wall\n    when 1 green vase accidentally falls\n    then there are [N-1] green vases standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9"
  },
  {
    "path": "examples/mocha-multi-library/lib/Wall.js",
    "content": "'use strict';\n\nvar Wall = function (items) {\n  this.items = items;\n  this.fall = function (n) {\n    this.items -= n;\n  };\n  this.returned = function () {\n    this.items++;\n  };\n};\n\nmodule.exports = Wall;\n"
  },
  {
    "path": "examples/mocha-multi-library/lib/bottle-steps.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar assert = require('assert');\nvar dictionary = require('./dictionary');\nvar Wall = require('./wall');\n\nmodule.exports = (function () {\n  var wall;\n\n  var library = English.library(dictionary)\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall = new Wall(number_of_bottles);\n      next();\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      wall.fall(number_of_falling_bottles);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      assert.equal(number_of_bottles, wall.items);\n      next();\n    });\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-multi-library/lib/common-steps.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar dictionary = require('./dictionary');\nvar Wall = require('./wall');\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var library = English.library(dictionary);\n\n  // Define common steps here\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-multi-library/lib/dictionary.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar Dictionary = Yadda.Dictionary;\n\nmodule.exports = (function () {\n  return new Dictionary().define('NUM', /(\\d+)/);\n})();\n"
  },
  {
    "path": "examples/mocha-multi-library/lib/vase-steps.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar assert = require('assert');\nvar dictionary = require('./dictionary');\nvar Wall = require('./wall');\n\nmodule.exports = (function () {\n  var wall;\n  var library = English.library(dictionary)\n\n    .given('$NUM green vases are standing on the wall', function (number_of_vases, next) {\n      wall = new Wall(number_of_vases);\n      next();\n    })\n\n    .when('$NUM green vase accidentally falls', function (number_of_falling_vases, next) {\n      wall.fall(number_of_falling_vases);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM green vases standing on the wall', function (number_of_vases, next) {\n      assert.equal(number_of_vases, wall.items);\n      next();\n    });\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-multi-library/package.json",
    "content": "{\n  \"name\": \"yadda-mocha-multi-library-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/mocha-multi-library/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\n/*\nPlease note this is just one way to import different libraries per feature\nThe downsides of this approach are that it pollutes the specification\nand doesn't support running the same specification with different libraries,\nwhich can be useful if the application under test supports multiple\ninterfaces (Rest, Web, CLI, etc)\n*/\n\nvar path = require('path');\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var libraries = require_feature_libraries(feature);\n    var yadda = Yadda.createInstance(libraries);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n\nfunction require_feature_libraries(feature) {\n  return feature.annotations.libraries.split(', ').reduce(require_library, []);\n}\n\nfunction require_library(libraries, library) {\n  return libraries.concat(require('./lib/' + library + '-steps'));\n}\n"
  },
  {
    "path": "examples/mocha-sync/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/mocha-sync\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/mocha-sync/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/mocha-sync/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/mocha-sync/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/mocha-sync/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n\n  var library = English.library(dictionary)\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles) {\n      wall = new Wall(number_of_bottles);\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles) {\n      wall.fall(number_of_falling_bottles);\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles) {\n      assert.equal(number_of_bottles, wall.bottles);\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/mocha-sync/features/bottles.feature",
    "content": "Feature: Mocha Synchronous Example\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Pending\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n\nScenario Outline: [N] bottles are standing on a wall\n\n    Given [N] green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are [N-1] green bottles standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/mocha-sync/package.json",
    "content": "{\n  \"name\": \"yadda-mocha-sync-example\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  }\n}\n"
  },
  {
    "path": "examples/mocha-sync/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step) {\n        yadda.run(step);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/multiline-examples-table/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/multiline-examples-table/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/multiline-examples-table/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/multiline-examples-table/features/transpile.feature",
    "content": "Feature: Multline Examples Table\n\nScenario: [case] Scenario\n\n    Given I need to transpile [case]\n    When EcmaScript6=[EcmaScript6]\n    Then EcmaScript5=[EcmaScript5]\n\nExamples:\n  case             | EcmaScript6              | EcmaScript5\n  -----------------|--------------------------|-------------------------------\n  arrow function   | var r=arr.map((x)=>x*x); | \"use strict\";\n                   |                          |\n                   |                          | var r = arr.map(function (x) {\n                   |                          |   return x * x;\n                   |                          | });\n  -----------------|--------------------------|-------------------------------\n  template strings | var s=`x=${x}            | \"use strict\";\n                   | y=${y}`;                 |\n                   |                          | var s = \"x=\" + x + \"\\ny=\" + y;\n\n"
  },
  {
    "path": "examples/multiline-examples-table/package.json",
    "content": "{\n  \"name\": \"yadda-multiline-examples-table-example\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Yadda multiline examples table example\",\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"thr0w\",\n  \"license\": \"Apache2\",\n  \"dependencies\": {\n    \"babel\": \"^5.6.14\",\n    \"csv-parse\": \"^3.1.2\",\n    \"lodash\": \"^4.17.11\",\n    \"mocha\": \"^5.2.0\"\n  }\n}\n"
  },
  {
    "path": "examples/multiline-examples-table/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar parse = require('csv-parse');\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var transpileLibrary = require('./transpile-library');\n\n    var yadda = Yadda.createInstance(transpileLibrary);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/multiline-examples-table/transpile-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar babel = require('babel');\n\nmodule.exports = (function () {\n  var case_description;\n  var es6_code;\n  var cases = {};\n\n  var dictionary = new Dictionary().define('CASE', /(\\w+)/, unique).define('CODE', /([^\\u0000]*)/);\n  var library = English.library(dictionary)\n\n    .given('I need to transpile $CASE', function (s, next) {\n      case_description = s;\n      next();\n    })\n\n    .when('EcmaScript6=$CODE', function (code, next) {\n      es6_code = code;\n      next();\n    })\n\n    .then('EcmaScript5=$CODE', function (expected_es5_code, next) {\n      var result = babel.transform(es6_code, {\n        filename: case_description,\n        compact: false,\n      });\n\n      var actual_es5_code = result.code;\n\n      if (expected_es5_code.trim() != actual_es5_code.trim()) throw new Error(['transpile fail on ' + case_description, 'expected:', expected_es5_code, 'actual', actual_es5_code].join('\\n'));\n\n      next();\n    });\n\n  function unique(key, next) {\n    if (Object.keys(cases).indexOf(key) >= 0) return next(new Error('case: ' + key + ' is not unique'));\n    cases[key] = key;\n    next(null, key);\n  }\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/multiline-steps/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/multiline-steps/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/multiline-steps/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/multiline-steps/csv-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar parse = require('csv-parse');\nvar _ = require('lodash');\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var csv;\n\n  var dictionary = new Dictionary().define('csv', /([^\\u0000]*)/, csvConverter).define('name', /(\\w+)/, nameConverter);\n\n  var library = English.library(dictionary)\n\n    .given('a csv file\\n$csv', function (_csv, next) {\n      csv = _csv;\n      next();\n    })\n\n    .then('$name is older than $name', function (user1, user2, next) {\n      assert(user1.Age > user2.Age);\n      next();\n    });\n\n  function csvConverter(text, cb) {\n    parse(text, { auto_parse: true, columns: true }, function (err, doc, stats) {\n      cb(err, doc);\n    });\n  }\n\n  function nameConverter(name, cb) {\n    cb(\n      null,\n      _.find(csv, function (row) {\n        return row['First Name'] === name;\n      })\n    );\n  }\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/multiline-steps/features/multiline-steps.feature",
    "content": "Feature: Multiline Step Examples\n\n\nScenario: Parse a CSV multiline step\n\n    Given a csv file\n    --------------------------\n    First Name,Second Name,Age\n    John,Smith,41\n    Joe,Blogs,23\n    --------------------------\n    Then John is older than Joe\n\n\nScenario: Read a Poem\n\n    Good Times\n    ----------\n    May we go our separate ways,\n    Finding fortune and new friends.\n    But let us not forget these days,\n    Or let the good times ever end.\n\n    A poet with wiser words than mine,\n    Wrote that nothing gold can stay.\n    These are golden days we're in,\n    And so are bound to fade away.\n    ----------\n    Has 2 verses"
  },
  {
    "path": "examples/multiline-steps/package.json",
    "content": "{\n  \"name\": \"yadda-multiline-steps-example\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Yadda multiline steps example\",\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"license\": \"Apache2\",\n  \"dependencies\": {\n    \"csv-parse\": \"^4.4.6\",\n    \"lodash\": \"^4.17.11\",\n    \"mocha\": \"^5.2.0\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "examples/multiline-steps/poem-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar parse = require('csv-parse');\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var poem;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/, Yadda.converters.integer).define('poem', /([^\\u0000]*)/);\n\n  var library = English.library(dictionary)\n\n    .define('Good Times\\n$poem', function (_poem, next) {\n      poem = _poem;\n      next();\n    })\n\n    .define('Has $NUM verses', function (verses, next) {\n      assert(poem.split(/\\n\\n/).length === 2);\n      next();\n    });\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/multiline-steps/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar parse = require('csv-parse');\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var csvLibrary = require('./csv-library');\n    var poemLibrary = require('./poem-library');\n\n    var yadda = Yadda.createInstance([csvLibrary, poemLibrary]);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "examples/multiline-steps/transpile-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar babel = require('babel');\n\nmodule.exports = (function () {\n  var case_description;\n  var es6_code;\n  var cases = {};\n\n  var dictionary = new Dictionary().define('CASE', /(\\w+)/, unique).define('CODE', /([^\\u0000]*)/);\n  var library = English.library(dictionary)\n\n    .given('I need to transpile $CASE', function (s, next) {\n      case_description = s;\n      next();\n    })\n\n    .when('EcmaScript6=$CODE', function (code, next) {\n      es6_code = code;\n      next();\n    })\n\n    .then('EcmaScript5=$CODE', function (expected_es5_code, next) {\n      var result = babel.transform(es6_code, {\n        filename: case_description,\n        compact: false,\n      });\n\n      var actual_es5_code = result.code;\n\n      if (expected_es5_code.trim() != actual_es5_code.trim()) throw new Error(['transpile fail on ' + case_description, 'expected:', expected_es5_code, 'actual', actual_es5_code].join('\\n'));\n\n      next();\n    });\n\n  function unique(key, next) {\n    if (Object.keys(cases).indexOf(key) >= 0) return next(new Error('case: ' + key + ' is not unique'));\n    cases[key] = key;\n    next(null, key);\n  }\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/nightwatch/.gitignore",
    "content": "node_modules\n*.log\narchive/logs/*\narchive/screenshots/*\narchive/reports/*\n!.gitkeep\n\n"
  },
  {
    "path": "examples/nightwatch/archive/logs/.gitkeep",
    "content": ".gitkeep"
  },
  {
    "path": "examples/nightwatch/archive/screenshots/.gitkeep",
    "content": ".gitkeep"
  },
  {
    "path": "examples/nightwatch/nightwatch.conf.js",
    "content": "var adBlockPlus = require('adblock-plus-crx');\n\nmodule.exports = {\n  src_folders: ['tests/runner'],\n  output_folder: 'archive/reports',\n  custom_commands_path: 'tests/commands',\n  custom_assertions_path: 'tests/assertions',\n  page_objects_path: 'tests/pages',\n  globals_path: '',\n  test_runner: {\n    type: 'mocha',\n    options: {\n      timeout: '10000',\n      slow: '5000',\n    },\n  },\n\n  selenium: {\n    start_process: true,\n    server_path: './node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.48.2.jar',\n    log_path: 'archive/logs',\n    host: '127.0.0.1',\n    port: 4444,\n    cli_args: {\n      'webdriver.chrome.driver': './node_modules/chromedriver/bin/chromedriver',\n      'webdriver.ie.driver': '',\n    },\n  },\n\n  test_settings: {\n    default: {\n      launch_url: 'https://www.tes.com',\n      selenium_host: 'localhost',\n      silent: true,\n      screenshots: {\n        enabled: true,\n        on_failure: true,\n        path: 'archive/screenshots',\n      },\n      desiredCapabilities: {\n        javascriptEnabled: true,\n        acceptSslCerts: true,\n        browserName: 'chrome',\n        chromeOptions: {\n          args: ['no-sandbox'],\n          extensions: [adBlockPlus.base64()],\n        },\n      },\n      globals: {\n        waitForConditionTimeout: 10000,\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "examples/nightwatch/package.json",
    "content": "{\n  \"name\": \"yadda-nightwatch-example\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"adblock-plus-crx\": \"^2.1.2\",\n    \"async\": \"^2.6.1\",\n    \"chalk\": \"^2.4.1\",\n    \"chromedriver\": \"^2.42.0\",\n    \"debug\": \"^4.0.1\",\n    \"glob\": \"^7.1.3\",\n    \"lodash\": \"^4.17.11\",\n    \"moment\": \"^2.22.2\",\n    \"nightwatch\": \"^0.9.21\",\n    \"ramda\": \"^0.18.0\",\n    \"request\": \"^2.88.0\",\n    \"require-all\": \"^3.0.0\",\n    \"selenium-server-standalone-jar\": \"2.48.2\"\n  },\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"test\": \"pkill -f selenium || true && java -version && nightwatch\",\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"jenkins\": \"node_modules/.bin/nightwatch --env jenkins\",\n    \"prepush\": \"npm test\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "examples/nightwatch/tests/assertions/.gitkeep",
    "content": ".gitkeep"
  },
  {
    "path": "examples/nightwatch/tests/commands/.gitkeep",
    "content": ".gitkeep"
  },
  {
    "path": "examples/nightwatch/tests/converters/filter.js",
    "content": "var filters = {\n  'London teaching jobs': {\n    locations: 'United Kingdom:England:London',\n    positions: 'Teacher',\n  },\n};\n\nmodule.exports = function (key, cb) {\n  cb(null, filters[key]);\n};\n"
  },
  {
    "path": "examples/nightwatch/tests/converters/index.js",
    "content": "module.exports = require('require-all')(__dirname);\n"
  },
  {
    "path": "examples/nightwatch/tests/features/job-search.spec",
    "content": "Feature: Job Search\n\nScenario: Search for a job from search bar\n\n    When I view the jobs home page\n    And search for \"teacher of mathematics\"\n    Then I should be shown the search results page\n    containing a list of at least 3 jobs\n\nScenario: Displays a friendly message when no results are found\n\n    When I view the jobs home page\n    And search for \"something that does not exist\"\n    Then I should be shown the search results page\n    But be informed that there are no results\n\nScenario: Search for a job from the search page\n\n    When I view the jobs search page\n    And I filter by London teaching jobs\n    Then I should be shown the search results page\n    containing a list of at least 3 jobs\n"
  },
  {
    "path": "examples/nightwatch/tests/pages/jobsHome.js",
    "content": "var debug = require('debug')('testsuite:jobsHome');\nvar R = require('ramda');\n\nmodule.exports = {\n  url: function () {\n    return this.api.launchUrl + '/jobs';\n  },\n  elements: {\n    main: {\n      selector: 'main[data-type=\"jobs-home-live\"]',\n    },\n    keywordsInput: {\n      selector: '#job-hubs-search__keywords',\n    },\n    searchButton: {\n      selector: '.job-hubs-search button',\n    },\n    searchCount: {\n      selector: '.seo-number-of-jobs',\n    },\n  },\n  commands: [\n    {\n      browse: function (facetName) {\n        debug('Browsing %s', facetName);\n        var selector = '.facet-items__item[data-id=\"' + facetName + '\"]';\n        return this.waitForElementVisible(selector).click(selector);\n      },\n      search: function (keywords) {\n        debug('Search for %s', keywords);\n        this.setValue('@keywordsInput', keywords);\n        this.click('@searchButton');\n      },\n    },\n  ],\n};\n"
  },
  {
    "path": "examples/nightwatch/tests/pages/jobsSearch.js",
    "content": "var debug = require('debug')('testsuite:jobsSearch');\nvar R = require('ramda');\nvar Url = require('url');\n\nmodule.exports = {\n  url: function () {\n    return this.api.launchUrl + '/jobs/search';\n  },\n  elements: {\n    jobListing: {\n      selector: '.t-jobs-listing',\n    },\n    searchButton: {\n      selector: '.t-keyword-search-button',\n    },\n    jobs: {\n      selector: '.tds-job-card',\n    },\n    noResults: {\n      selector: '.t-no-results',\n    },\n  },\n  commands: [\n    {\n      assertSearchResults: function () {\n        return this.waitForElementVisible('@jobListing');\n      },\n    },\n    {\n      assertVisibleJobsCount: function (count) {\n        var self = this;\n        self.waitForElementVisible('@jobListing');\n        return self.api.elements('css selector', '.tds-job-card', function (result) {\n          self.assert.ok(result.value.length >= count);\n        });\n      },\n    },\n    {\n      assertNoResults: function () {\n        return this.waitForElementVisible('@noResults');\n      },\n    },\n    {\n      search: function (keywords) {\n        debug('Search for %s', keywords);\n        this.setValue('@keywordsInput', keywords);\n        this.click('@searchButton');\n      },\n    },\n    {\n      refine: function (filters) {\n        debug('refine');\n        var searchUrl = Url.parse(this.api.launchUrl + '/jobs/search');\n        var refinedSearchUrl = Url.format(R.mergeAll([searchUrl, { query: filters }]), true);\n        return this.api.url(refinedSearchUrl);\n      },\n    },\n  ],\n};\n"
  },
  {
    "path": "examples/nightwatch/tests/runner/index.js",
    "content": "var assert = require('assert');\nvar R = require('ramda');\nvar Yadda = require('yadda');\nvar fs = require('fs');\nvar glob = require('glob');\nvar chalk = require('chalk');\nvar stepDefinitions = [require('../steps/jobsHome'), require('../steps/jobsSearch')];\n\nvar featureParser = new Yadda.parsers.FeatureParser();\nvar features = {};\n\nbefore(function (client, done) {\n  done();\n});\n\nafter(function (client, done) {\n  client.end(function () {\n    done();\n  });\n});\n\nglob.sync('tests/features/**/*.spec').forEach(function (file) {\n  var text = fs.readFileSync(file, 'utf8');\n  var feature = featureParser.parse(text);\n\n  describe(feature, function () {\n    feature.scenarios.forEach(function (scenario) {\n      describe(scenario, function () {\n        var yadda = Yadda.createInstance(stepDefinitions, { ctx: {} });\n        scenario.steps.forEach(function (step) {\n          it(step, function (browser) {\n            browser.perform(function (client, done) {\n              yadda.run(step, { browser: browser }, function (err) {\n                browser.assert.ifError(err);\n                done();\n              });\n            });\n          });\n        });\n      });\n    });\n  });\n});\n\nfunction describe(subject, next) {\n  if (subject.annotations && subject.annotations.pending) return global.describe.skip(subject.title, next);\n  if (subject.annotations && subject.annotations.only) return global.describe.only(subject.title, next);\n  global.describe(subject.title, next);\n}\n"
  },
  {
    "path": "examples/nightwatch/tests/steps/dictionary.js",
    "content": "var Yadda = require('yadda');\nvar converters = require('../converters');\n\nmodule.exports = new Yadda.Dictionary().define('count', /(\\d+)/, Yadda.converters.integer).define('filters', /(.*)/, converters.filter);\n"
  },
  {
    "path": "examples/nightwatch/tests/steps/jobsHome.js",
    "content": "var Yadda = require('yadda');\nvar dictionary = require('./dictionary');\nvar R = require('ramda');\n\nmodule.exports = (function () {\n  return Yadda.localisation.English.library(dictionary)\n    .when('I view the jobs home page', function () {\n      this.browser.page.jobsHome().navigate();\n    })\n    .when('search for $keywords', function (keywords) {\n      this.browser.page.jobsHome().search(keywords);\n    });\n})();\n"
  },
  {
    "path": "examples/nightwatch/tests/steps/jobsSearch.js",
    "content": "var Yadda = require('yadda');\nvar dictionary = require('./dictionary');\nvar R = require('ramda');\nvar dictionary = require('./dictionary');\n\nmodule.exports = (function () {\n  return Yadda.localisation.English.library(dictionary)\n    .when('I view the jobs search page', function () {\n      this.browser.page.jobsSearch().navigate();\n    })\n    .when('I filter by $filters', function (filters) {\n      this.browser.page.jobsSearch().refine(filters);\n    })\n    .then('I should be shown the search results page', function () {\n      this.browser.page.jobsSearch().assertSearchResults();\n    })\n    .define('containing a list of at least $count jobs', function (count) {\n      this.browser.page.jobsSearch().assertVisibleJobsCount(count);\n    })\n    .then('be informed that there are no results', function () {\n      this.browser.page.jobsSearch().assertNoResults();\n    });\n})();\n"
  },
  {
    "path": "examples/nodeunit/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/nodeunit\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/nodeunit/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\nodeunit test.js\nendlocal"
  },
  {
    "path": "examples/nodeunit/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/nodeunit/bin/example.sh",
    "content": "#!/bin/bash\n\nnode_modules/.bin/nodeunit test.js"
  },
  {
    "path": "examples/nodeunit/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\n\nmodule.exports = (function () {\n  var wall;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n  var library = English.library(dictionary)\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall = new Wall(number_of_bottles);\n      next();\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      wall.fall(number_of_falling_bottles);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      this.test.equal(number_of_bottles, wall.bottles);\n      next();\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n  return library;\n})();\n"
  },
  {
    "path": "examples/nodeunit/features/bottles.feature",
    "content": "Scenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall "
  },
  {
    "path": "examples/nodeunit/package.json",
    "content": "{\n  \"name\": \"yadda-nodeunit-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"nodeunit\": \"^0.11.3\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/nodeunit/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar fs = require('fs');\nvar Yadda = require('../../lib/index');\nvar parser = new Yadda.parsers.FeatureParser();\nvar library = require('./bottles-library');\nvar yadda = new Yadda.createInstance(library);\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  var text = fs.readFileSync(file, 'utf8');\n  var feature = parser.parse(text);\n\n  feature.scenarios.forEach(function (scenario) {\n    exports[scenario.title] = function (test) {\n      yadda.run(scenario.steps, { test: test }, test.done);\n    };\n  });\n});\n"
  },
  {
    "path": "examples/qunit/README.md",
    "content": "```\ncd examples\\qunit\nnpm test\n```\n"
  },
  {
    "path": "examples/qunit/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nstart test.html\nendlocal"
  },
  {
    "path": "examples/qunit/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/qunit/bin/example.sh",
    "content": "#!/bin/bash\n\nopen test.html"
  },
  {
    "path": "examples/qunit/bottles-library.js",
    "content": "/* jslint node: true */\n/* global equal */\n'use strict';\n\nvar Dictionary = require('yadda').Dictionary;\nvar English = require('yadda').localisation.English;\n\nvar wall;\nvar dictionary = new Dictionary().define('NUM', /(\\d+)/);\nvar library = English.library(dictionary)\n\n  .given('$NUM green bottles are standing on the wall', function (number_of_bottles) {\n    wall = new Wall(number_of_bottles);\n  })\n\n  .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles) {\n    wall.fall(number_of_falling_bottles);\n  })\n\n  .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles) {\n    equal(number_of_bottles, wall.bottles);\n  });\n\nvar Wall = function (bottles) {\n  this.bottles = bottles;\n  this.fall = function (n) {\n    this.bottles -= n;\n  };\n  this.returned = function () {\n    this.bottles++;\n  };\n};\n"
  },
  {
    "path": "examples/qunit/lib/qunit-1.10.0.css",
    "content": "/**\n * QUnit v1.10.0 - A JavaScript Unit Testing Framework\n *\n * http://qunitjs.com\n *\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests,\n#qunit-header,\n#qunit-banner,\n#qunit-testrunner-toolbar,\n#qunit-userAgent,\n#qunit-testresult {\n  font-family: 'Helvetica Neue Light', 'HelveticaNeue-Light', 'Helvetica Neue', Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar,\n#qunit-userAgent,\n#qunit-testresult,\n#qunit-tests li {\n  font-size: small;\n}\n#qunit-tests {\n  font-size: smaller;\n}\n\n/** Resets */\n\n#qunit-tests,\n#qunit-tests ol,\n#qunit-header,\n#qunit-banner,\n#qunit-userAgent,\n#qunit-testresult,\n#qunit-modulefilter {\n  margin: 0;\n  padding: 0;\n}\n\n/** Header */\n\n#qunit-header {\n  padding: 0.5em 0 0.5em 1em;\n\n  color: #8699a4;\n  background-color: #0d3349;\n\n  font-size: 1.5em;\n  line-height: 1em;\n  font-weight: normal;\n\n  border-radius: 5px 5px 0 0;\n  -moz-border-radius: 5px 5px 0 0;\n  -webkit-border-top-right-radius: 5px;\n  -webkit-border-top-left-radius: 5px;\n}\n\n#qunit-header a {\n  text-decoration: none;\n  color: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n  color: #fff;\n}\n\n#qunit-testrunner-toolbar label {\n  display: inline-block;\n  padding: 0 0.5em 0 0.1em;\n}\n\n#qunit-banner {\n  height: 5px;\n}\n\n#qunit-testrunner-toolbar {\n  padding: 0.5em 0 0.5em 2em;\n  color: #5e740b;\n  background-color: #eee;\n  overflow: hidden;\n}\n\n#qunit-userAgent {\n  padding: 0.5em 0 0.5em 2.5em;\n  background-color: #2b81af;\n  color: #fff;\n  text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n#qunit-modulefilter-container {\n  float: right;\n}\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n  list-style-position: inside;\n}\n\n#qunit-tests li {\n  padding: 0.4em 0.5em 0.4em 2.5em;\n  border-bottom: 1px solid #fff;\n  list-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass,\n#qunit-tests.hidepass li.running {\n  display: none;\n}\n\n#qunit-tests li strong {\n  cursor: pointer;\n}\n\n#qunit-tests li a {\n  padding: 0.5em;\n  color: #c2ccd1;\n  text-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n  color: #000;\n}\n\n#qunit-tests ol {\n  margin-top: 0.5em;\n  padding: 0.5em;\n\n  background-color: #fff;\n\n  border-radius: 5px;\n  -moz-border-radius: 5px;\n  -webkit-border-radius: 5px;\n}\n\n#qunit-tests table {\n  border-collapse: collapse;\n  margin-top: 0.2em;\n}\n\n#qunit-tests th {\n  text-align: right;\n  vertical-align: top;\n  padding: 0 0.5em 0 0;\n}\n\n#qunit-tests td {\n  vertical-align: top;\n}\n\n#qunit-tests pre {\n  margin: 0;\n  white-space: pre-wrap;\n  word-wrap: break-word;\n}\n\n#qunit-tests del {\n  background-color: #e0f2be;\n  color: #374e0c;\n  text-decoration: none;\n}\n\n#qunit-tests ins {\n  background-color: #ffcaca;\n  color: #500;\n  text-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts {\n  color: black;\n}\n#qunit-tests b.passed {\n  color: #5e740b;\n}\n#qunit-tests b.failed {\n  color: #710909;\n}\n\n#qunit-tests li li {\n  padding: 5px;\n  background-color: #fff;\n  border-bottom: none;\n  list-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n  color: #3c510c;\n  background-color: #fff;\n  border-left: 10px solid #c6e746;\n}\n\n#qunit-tests .pass {\n  color: #528ce0;\n  background-color: #d2e0e6;\n}\n#qunit-tests .pass .test-name {\n  color: #366097;\n}\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected {\n  color: #999999;\n}\n\n#qunit-banner.qunit-pass {\n  background-color: #c6e746;\n}\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n  color: #710909;\n  background-color: #fff;\n  border-left: 10px solid #ee5757;\n  white-space: pre;\n}\n\n#qunit-tests > li:last-child {\n  border-radius: 0 0 5px 5px;\n  -moz-border-radius: 0 0 5px 5px;\n  -webkit-border-bottom-right-radius: 5px;\n  -webkit-border-bottom-left-radius: 5px;\n}\n\n#qunit-tests .fail {\n  color: #000000;\n  background-color: #ee5757;\n}\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name {\n  color: #000000;\n}\n\n#qunit-tests .fail .test-actual {\n  color: #ee5757;\n}\n#qunit-tests .fail .test-expected {\n  color: green;\n}\n\n#qunit-banner.qunit-fail {\n  background-color: #ee5757;\n}\n\n/** Result */\n\n#qunit-testresult {\n  padding: 0.5em 0.5em 0.5em 2.5em;\n\n  color: #2b81af;\n  background-color: #d2e0e6;\n\n  border-bottom: 1px solid white;\n}\n#qunit-testresult .module-name {\n  font-weight: bold;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n  position: absolute;\n  top: -10000px;\n  left: -10000px;\n  width: 1000px;\n  height: 1000px;\n}\n"
  },
  {
    "path": "examples/qunit/lib/qunit-1.10.0.js",
    "content": "/**\n * QUnit v1.10.0 - A JavaScript Unit Testing Framework\n *\n * http://qunitjs.com\n *\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n(function (window) {\n  var QUnit,\n    config,\n    onErrorFnPrev,\n    testId = 0,\n    fileName = (sourceFromStacktrace(0) || '').replace(/(:\\d+)+\\)?/, '').replace(/.+\\//, ''),\n    toString = Object.prototype.toString,\n    hasOwn = Object.prototype.hasOwnProperty,\n    // Keep a local reference to Date (GH-283)\n    Date = window.Date,\n    defined = {\n      setTimeout: typeof window.setTimeout !== 'undefined',\n      sessionStorage: (function () {\n        var x = 'qunit-test-string';\n        try {\n          sessionStorage.setItem(x, x);\n          sessionStorage.removeItem(x);\n          return true;\n        } catch (e) {\n          return false;\n        }\n      })(),\n    };\n\n  function Test(settings) {\n    extend(this, settings);\n    this.assertions = [];\n    this.testNumber = ++Test.count;\n  }\n\n  Test.count = 0;\n\n  Test.prototype = {\n    init: function () {\n      var a,\n        b,\n        li,\n        tests = id('qunit-tests');\n\n      if (tests) {\n        b = document.createElement('strong');\n        b.innerHTML = this.name;\n\n        // `a` initialized at top of scope\n        a = document.createElement('a');\n        a.innerHTML = 'Rerun';\n        a.href = QUnit.url({ testNumber: this.testNumber });\n\n        li = document.createElement('li');\n        li.appendChild(b);\n        li.appendChild(a);\n        li.className = 'running';\n        li.id = this.id = 'qunit-test-output' + testId++;\n\n        tests.appendChild(li);\n      }\n    },\n    setup: function () {\n      if (this.module !== config.previousModule) {\n        if (config.previousModule) {\n          runLoggingCallbacks('moduleDone', QUnit, {\n            name: config.previousModule,\n            failed: config.moduleStats.bad,\n            passed: config.moduleStats.all - config.moduleStats.bad,\n            total: config.moduleStats.all,\n          });\n        }\n        config.previousModule = this.module;\n        config.moduleStats = { all: 0, bad: 0 };\n        runLoggingCallbacks('moduleStart', QUnit, {\n          name: this.module,\n        });\n      } else if (config.autorun) {\n        runLoggingCallbacks('moduleStart', QUnit, {\n          name: this.module,\n        });\n      }\n\n      config.current = this;\n\n      this.testEnvironment = extend(\n        {\n          setup: function () {},\n          teardown: function () {},\n        },\n        this.moduleTestEnvironment\n      );\n\n      runLoggingCallbacks('testStart', QUnit, {\n        name: this.testName,\n        module: this.module,\n      });\n\n      // allow utility functions to access the current test environment\n      // TODO why??\n      QUnit.current_testEnvironment = this.testEnvironment;\n\n      if (!config.pollution) {\n        saveGlobal();\n      }\n      if (config.notrycatch) {\n        this.testEnvironment.setup.call(this.testEnvironment);\n        return;\n      }\n      try {\n        this.testEnvironment.setup.call(this.testEnvironment);\n      } catch (e) {\n        QUnit.pushFailure('Setup failed on ' + this.testName + ': ' + e.message, extractStacktrace(e, 1));\n      }\n    },\n    run: function () {\n      config.current = this;\n\n      var running = id('qunit-testresult');\n\n      if (running) {\n        running.innerHTML = 'Running: <br/>' + this.name;\n      }\n\n      if (this.async) {\n        QUnit.stop();\n      }\n\n      if (config.notrycatch) {\n        this.callback.call(this.testEnvironment, QUnit.assert);\n        return;\n      }\n\n      try {\n        this.callback.call(this.testEnvironment, QUnit.assert);\n      } catch (e) {\n        QUnit.pushFailure('Died on test #' + (this.assertions.length + 1) + ' ' + this.stack + ': ' + e.message, extractStacktrace(e, 0));\n        // else next test will carry the responsibility\n        saveGlobal();\n\n        // Restart the tests if they're blocking\n        if (config.blocking) {\n          QUnit.start();\n        }\n      }\n    },\n    teardown: function () {\n      config.current = this;\n      if (config.notrycatch) {\n        this.testEnvironment.teardown.call(this.testEnvironment);\n        return;\n      } else {\n        try {\n          this.testEnvironment.teardown.call(this.testEnvironment);\n        } catch (e) {\n          QUnit.pushFailure('Teardown failed on ' + this.testName + ': ' + e.message, extractStacktrace(e, 1));\n        }\n      }\n      checkPollution();\n    },\n    finish: function () {\n      config.current = this;\n      if (config.requireExpects && this.expected == null) {\n        QUnit.pushFailure('Expected number of assertions to be defined, but expect() was not called.', this.stack);\n      } else if (this.expected != null && this.expected != this.assertions.length) {\n        QUnit.pushFailure('Expected ' + this.expected + ' assertions, but ' + this.assertions.length + ' were run', this.stack);\n      } else if (this.expected == null && !this.assertions.length) {\n        QUnit.pushFailure('Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.', this.stack);\n      }\n\n      var assertion,\n        a,\n        b,\n        i,\n        li,\n        ol,\n        test = this,\n        good = 0,\n        bad = 0,\n        tests = id('qunit-tests');\n\n      config.stats.all += this.assertions.length;\n      config.moduleStats.all += this.assertions.length;\n\n      if (tests) {\n        ol = document.createElement('ol');\n\n        for (i = 0; i < this.assertions.length; i++) {\n          assertion = this.assertions[i];\n\n          li = document.createElement('li');\n          li.className = assertion.result ? 'pass' : 'fail';\n          li.innerHTML = assertion.message || (assertion.result ? 'okay' : 'failed');\n          ol.appendChild(li);\n\n          if (assertion.result) {\n            good++;\n          } else {\n            bad++;\n            config.stats.bad++;\n            config.moduleStats.bad++;\n          }\n        }\n\n        // store result when possible\n        if (QUnit.config.reorder && defined.sessionStorage) {\n          if (bad) {\n            sessionStorage.setItem('qunit-test-' + this.module + '-' + this.testName, bad);\n          } else {\n            sessionStorage.removeItem('qunit-test-' + this.module + '-' + this.testName);\n          }\n        }\n\n        if (bad === 0) {\n          ol.style.display = 'none';\n        }\n\n        // `b` initialized at top of scope\n        b = document.createElement('strong');\n        b.innerHTML = this.name + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + '</b>, ' + this.assertions.length + ')</b>';\n\n        addEvent(b, 'click', function () {\n          var next = b.nextSibling.nextSibling,\n            display = next.style.display;\n          next.style.display = display === 'none' ? 'block' : 'none';\n        });\n\n        addEvent(b, 'dblclick', function (e) {\n          var target = e && e.target ? e.target : window.event.srcElement;\n          if (target.nodeName.toLowerCase() == 'span' || target.nodeName.toLowerCase() == 'b') {\n            target = target.parentNode;\n          }\n          if (window.location && target.nodeName.toLowerCase() === 'strong') {\n            window.location = QUnit.url({ testNumber: test.testNumber });\n          }\n        });\n\n        // `li` initialized at top of scope\n        li = id(this.id);\n        li.className = bad ? 'fail' : 'pass';\n        li.removeChild(li.firstChild);\n        a = li.firstChild;\n        li.appendChild(b);\n        li.appendChild(a);\n        li.appendChild(ol);\n      } else {\n        for (i = 0; i < this.assertions.length; i++) {\n          if (!this.assertions[i].result) {\n            bad++;\n            config.stats.bad++;\n            config.moduleStats.bad++;\n          }\n        }\n      }\n\n      runLoggingCallbacks('testDone', QUnit, {\n        name: this.testName,\n        module: this.module,\n        failed: bad,\n        passed: this.assertions.length - bad,\n        total: this.assertions.length,\n      });\n\n      QUnit.reset();\n\n      config.current = undefined;\n    },\n\n    queue: function () {\n      var bad,\n        test = this;\n\n      synchronize(function () {\n        test.init();\n      });\n      function run() {\n        // each of these can by async\n        synchronize(function () {\n          test.setup();\n        });\n        synchronize(function () {\n          test.run();\n        });\n        synchronize(function () {\n          test.teardown();\n        });\n        synchronize(function () {\n          test.finish();\n        });\n      }\n\n      // `bad` initialized at top of scope\n      // defer when previous test run passed, if storage is available\n      bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem('qunit-test-' + this.module + '-' + this.testName);\n\n      if (bad) {\n        run();\n      } else {\n        synchronize(run, true);\n      }\n    },\n  };\n\n  // Root QUnit object.\n  // `QUnit` initialized at top of scope\n  QUnit = {\n    // call on start of module test to prepend name to all tests\n    module: function (name, testEnvironment) {\n      config.currentModule = name;\n      config.currentModuleTestEnvironment = testEnvironment;\n      config.modules[name] = true;\n    },\n\n    asyncTest: function (testName, expected, callback) {\n      if (arguments.length === 2) {\n        callback = expected;\n        expected = null;\n      }\n\n      QUnit.test(testName, expected, callback, true);\n    },\n\n    test: function (testName, expected, callback, async) {\n      var test,\n        name = \"<span class='test-name'>\" + escapeInnerText(testName) + '</span>';\n\n      if (arguments.length === 2) {\n        callback = expected;\n        expected = null;\n      }\n\n      if (config.currentModule) {\n        name = \"<span class='module-name'>\" + config.currentModule + '</span>: ' + name;\n      }\n\n      test = new Test({\n        name: name,\n        testName: testName,\n        expected: expected,\n        async: async,\n        callback: callback,\n        module: config.currentModule,\n        moduleTestEnvironment: config.currentModuleTestEnvironment,\n        stack: sourceFromStacktrace(2),\n      });\n\n      if (!validTest(test)) {\n        return;\n      }\n\n      test.queue();\n    },\n\n    // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.\n    expect: function (asserts) {\n      if (arguments.length === 1) {\n        config.current.expected = asserts;\n      } else {\n        return config.current.expected;\n      }\n    },\n\n    start: function (count) {\n      config.semaphore -= count || 1;\n      // don't start until equal number of stop-calls\n      if (config.semaphore > 0) {\n        return;\n      }\n      // ignore if start is called more often then stop\n      if (config.semaphore < 0) {\n        config.semaphore = 0;\n      }\n      // A slight delay, to avoid any current callbacks\n      if (defined.setTimeout) {\n        window.setTimeout(function () {\n          if (config.semaphore > 0) {\n            return;\n          }\n          if (config.timeout) {\n            clearTimeout(config.timeout);\n          }\n\n          config.blocking = false;\n          process(true);\n        }, 13);\n      } else {\n        config.blocking = false;\n        process(true);\n      }\n    },\n\n    stop: function (count) {\n      config.semaphore += count || 1;\n      config.blocking = true;\n\n      if (config.testTimeout && defined.setTimeout) {\n        clearTimeout(config.timeout);\n        config.timeout = window.setTimeout(function () {\n          QUnit.ok(false, 'Test timed out');\n          config.semaphore = 1;\n          QUnit.start();\n        }, config.testTimeout);\n      }\n    },\n  };\n\n  // Asssert helpers\n  // All of these must call either QUnit.push() or manually do:\n  // - runLoggingCallbacks( \"log\", .. );\n  // - config.current.assertions.push({ .. });\n  QUnit.assert = {\n    /**\n     * Asserts rough true-ish result.\n     * @name ok\n     * @function\n     * @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n     */\n    ok: function (result, msg) {\n      if (!config.current) {\n        throw new Error('ok() assertion outside test context, was ' + sourceFromStacktrace(2));\n      }\n      result = !!result;\n\n      var source,\n        details = {\n          module: config.current.module,\n          name: config.current.testName,\n          result: result,\n          message: msg,\n        };\n\n      msg = escapeInnerText(msg || (result ? 'okay' : 'failed'));\n      msg = \"<span class='test-message'>\" + msg + '</span>';\n\n      if (!result) {\n        source = sourceFromStacktrace(2);\n        if (source) {\n          details.source = source;\n          msg += \"<table><tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText(source) + '</pre></td></tr></table>';\n        }\n      }\n      runLoggingCallbacks('log', QUnit, details);\n      config.current.assertions.push({\n        result: result,\n        message: msg,\n      });\n    },\n\n    /**\n     * Assert that the first two arguments are equal, with an optional message.\n     * Prints out both actual and expected values.\n     * @name equal\n     * @function\n     * @example equal( format( \"Received {0} bytes.\", 2), \"Received 2 bytes.\", \"format() replaces {0} with next argument\" );\n     */\n    equal: function (actual, expected, message) {\n      QUnit.push(expected == actual, actual, expected, message);\n    },\n\n    /**\n     * @name notEqual\n     * @function\n     */\n    notEqual: function (actual, expected, message) {\n      QUnit.push(expected != actual, actual, expected, message);\n    },\n\n    /**\n     * @name deepEqual\n     * @function\n     */\n    deepEqual: function (actual, expected, message) {\n      QUnit.push(QUnit.equiv(actual, expected), actual, expected, message);\n    },\n\n    /**\n     * @name notDeepEqual\n     * @function\n     */\n    notDeepEqual: function (actual, expected, message) {\n      QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);\n    },\n\n    /**\n     * @name strictEqual\n     * @function\n     */\n    strictEqual: function (actual, expected, message) {\n      QUnit.push(expected === actual, actual, expected, message);\n    },\n\n    /**\n     * @name notStrictEqual\n     * @function\n     */\n    notStrictEqual: function (actual, expected, message) {\n      QUnit.push(expected !== actual, actual, expected, message);\n    },\n\n    throws: function (block, expected, message) {\n      var actual,\n        ok = false;\n\n      // 'expected' is optional\n      if (typeof expected === 'string') {\n        message = expected;\n        expected = null;\n      }\n\n      config.current.ignoreGlobalErrors = true;\n      try {\n        block.call(config.current.testEnvironment);\n      } catch (e) {\n        actual = e;\n      }\n      config.current.ignoreGlobalErrors = false;\n\n      if (actual) {\n        // we don't want to validate thrown error\n        if (!expected) {\n          ok = true;\n          // expected is a regexp\n        } else if (QUnit.objectType(expected) === 'regexp') {\n          ok = expected.test(actual);\n          // expected is a constructor\n        } else if (actual instanceof expected) {\n          ok = true;\n          // expected is a validation function which returns true is validation passed\n        } else if (expected.call({}, actual) === true) {\n          ok = true;\n        }\n\n        QUnit.push(ok, actual, null, message);\n      } else {\n        QUnit.pushFailure(message, null, 'No exception was thrown.');\n      }\n    },\n  };\n\n  /**\n   * @deprecate since 1.8.0\n   * Kept assertion helpers in root for backwards compatibility\n   */\n  extend(QUnit, QUnit.assert);\n\n  /**\n   * @deprecated since 1.9.0\n   * Kept global \"raises()\" for backwards compatibility\n   */\n  QUnit.raises = QUnit.assert.throws;\n\n  /**\n   * @deprecated since 1.0.0, replaced with error pushes since 1.3.0\n   * Kept to avoid TypeErrors for undefined methods.\n   */\n  QUnit.equals = function () {\n    QUnit.push(false, false, false, 'QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead');\n  };\n  QUnit.same = function () {\n    QUnit.push(false, false, false, 'QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead');\n  };\n\n  // We want access to the constructor's prototype\n  (function () {\n    function F() {}\n    F.prototype = QUnit;\n    QUnit = new F();\n    // Make F QUnit's constructor so that we can add to the prototype later\n    QUnit.constructor = F;\n  })();\n\n  /**\n   * Config object: Maintain internal state\n   * Later exposed as QUnit.config\n   * `config` initialized at top of scope\n   */\n  config = {\n    // The queue of tests to run\n    queue: [],\n\n    // block until document ready\n    blocking: true,\n\n    // when enabled, show only failing tests\n    // gets persisted through sessionStorage and can be changed in UI via checkbox\n    hidepassed: false,\n\n    // by default, run previously failed tests first\n    // very useful in combination with \"Hide passed tests\" checked\n    reorder: true,\n\n    // by default, modify document.title when suite is done\n    altertitle: true,\n\n    // when enabled, all tests must call expect()\n    requireExpects: false,\n\n    // add checkboxes that are persisted in the query-string\n    // when enabled, the id is set to `true` as a `QUnit.config` property\n    urlConfig: [\n      {\n        id: 'noglobals',\n        label: 'Check for Globals',\n        tooltip: 'Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings.',\n      },\n      {\n        id: 'notrycatch',\n        label: 'No try-catch',\n        tooltip: 'Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings.',\n      },\n    ],\n\n    // Set of all modules.\n    modules: {},\n\n    // logging callback queues\n    begin: [],\n    done: [],\n    log: [],\n    testStart: [],\n    testDone: [],\n    moduleStart: [],\n    moduleDone: [],\n  };\n\n  // Initialize more QUnit.config and QUnit.urlParams\n  (function () {\n    var i,\n      location = window.location || { search: '', protocol: 'file:' },\n      params = location.search.slice(1).split('&'),\n      length = params.length,\n      urlParams = {},\n      current;\n\n    if (params[0]) {\n      for (i = 0; i < length; i++) {\n        current = params[i].split('=');\n        current[0] = decodeURIComponent(current[0]);\n        // allow just a key to turn on a flag, e.g., test.html?noglobals\n        current[1] = current[1] ? decodeURIComponent(current[1]) : true;\n        urlParams[current[0]] = current[1];\n      }\n    }\n\n    QUnit.urlParams = urlParams;\n\n    // String search anywhere in moduleName+testName\n    config.filter = urlParams.filter;\n\n    // Exact match of the module name\n    config.module = urlParams.module;\n\n    config.testNumber = parseInt(urlParams.testNumber, 10) || null;\n\n    // Figure out if we're running the tests from a server or not\n    QUnit.isLocal = location.protocol === 'file:';\n  })();\n\n  // Export global variables, unless an 'exports' object exists,\n  // in that case we assume we're in CommonJS (dealt with on the bottom of the script)\n  if (typeof exports === 'undefined') {\n    extend(window, QUnit);\n\n    // Expose QUnit object\n    window.QUnit = QUnit;\n  }\n\n  // Extend QUnit object,\n  // these after set here because they should not be exposed as global functions\n  extend(QUnit, {\n    config: config,\n\n    // Initialize the configuration options\n    init: function () {\n      extend(config, {\n        stats: { all: 0, bad: 0 },\n        moduleStats: { all: 0, bad: 0 },\n        started: +new Date(),\n        updateRate: 1000,\n        blocking: false,\n        autostart: true,\n        autorun: false,\n        filter: '',\n        queue: [],\n        semaphore: 0,\n      });\n\n      var tests,\n        banner,\n        result,\n        qunit = id('qunit');\n\n      if (qunit) {\n        qunit.innerHTML = \"<h1 id='qunit-header'>\" + escapeInnerText(document.title) + '</h1>' + \"<h2 id='qunit-banner'></h2>\" + \"<div id='qunit-testrunner-toolbar'></div>\" + \"<h2 id='qunit-userAgent'></h2>\" + \"<ol id='qunit-tests'></ol>\";\n      }\n\n      tests = id('qunit-tests');\n      banner = id('qunit-banner');\n      result = id('qunit-testresult');\n\n      if (tests) {\n        tests.innerHTML = '';\n      }\n\n      if (banner) {\n        banner.className = '';\n      }\n\n      if (result) {\n        result.parentNode.removeChild(result);\n      }\n\n      if (tests) {\n        result = document.createElement('p');\n        result.id = 'qunit-testresult';\n        result.className = 'result';\n        tests.parentNode.insertBefore(result, tests);\n        result.innerHTML = 'Running...<br/>&nbsp;';\n      }\n    },\n\n    // Resets the test setup. Useful for tests that modify the DOM.\n    reset: function () {\n      var fixture = id('qunit-fixture');\n      if (fixture) {\n        fixture.innerHTML = config.fixture;\n      }\n    },\n\n    // Trigger an event on an element.\n    // @example triggerEvent( document.body, \"click\" );\n    triggerEvent: function (elem, type, event) {\n      if (document.createEvent) {\n        event = document.createEvent('MouseEvents');\n        event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\n        elem.dispatchEvent(event);\n      } else if (elem.fireEvent) {\n        elem.fireEvent('on' + type);\n      }\n    },\n\n    // Safe object type checking\n    is: function (type, obj) {\n      return QUnit.objectType(obj) == type;\n    },\n\n    objectType: function (obj) {\n      if (typeof obj === 'undefined') {\n        return 'undefined';\n        // consider: typeof null === object\n      }\n      if (obj === null) {\n        return 'null';\n      }\n\n      var type = toString.call(obj).match(/^\\[object\\s(.*)\\]$/)[1] || '';\n\n      switch (type) {\n        case 'Number':\n          if (isNaN(obj)) {\n            return 'nan';\n          }\n          return 'number';\n        case 'String':\n        case 'Boolean':\n        case 'Array':\n        case 'Date':\n        case 'RegExp':\n        case 'Function':\n          return type.toLowerCase();\n      }\n      if (typeof obj === 'object') {\n        return 'object';\n      }\n      return undefined;\n    },\n\n    push: function (result, actual, expected, message) {\n      if (!config.current) {\n        throw new Error('assertion outside test context, was ' + sourceFromStacktrace());\n      }\n\n      var output,\n        source,\n        details = {\n          module: config.current.module,\n          name: config.current.testName,\n          result: result,\n          message: message,\n          actual: actual,\n          expected: expected,\n        };\n\n      message = escapeInnerText(message) || (result ? 'okay' : 'failed');\n      message = \"<span class='test-message'>\" + message + '</span>';\n      output = message;\n\n      if (!result) {\n        expected = escapeInnerText(QUnit.jsDump.parse(expected));\n        actual = escapeInnerText(QUnit.jsDump.parse(actual));\n        output += \"<table><tr class='test-expected'><th>Expected: </th><td><pre>\" + expected + '</pre></td></tr>';\n\n        if (actual != expected) {\n          output += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + actual + '</pre></td></tr>';\n          output += \"<tr class='test-diff'><th>Diff: </th><td><pre>\" + QUnit.diff(expected, actual) + '</pre></td></tr>';\n        }\n\n        source = sourceFromStacktrace();\n\n        if (source) {\n          details.source = source;\n          output += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText(source) + '</pre></td></tr>';\n        }\n\n        output += '</table>';\n      }\n\n      runLoggingCallbacks('log', QUnit, details);\n\n      config.current.assertions.push({\n        result: !!result,\n        message: output,\n      });\n    },\n\n    pushFailure: function (message, source, actual) {\n      if (!config.current) {\n        throw new Error('pushFailure() assertion outside test context, was ' + sourceFromStacktrace(2));\n      }\n\n      var output,\n        details = {\n          module: config.current.module,\n          name: config.current.testName,\n          result: false,\n          message: message,\n        };\n\n      message = escapeInnerText(message) || 'error';\n      message = \"<span class='test-message'>\" + message + '</span>';\n      output = message;\n\n      output += '<table>';\n\n      if (actual) {\n        output += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + escapeInnerText(actual) + '</pre></td></tr>';\n      }\n\n      if (source) {\n        details.source = source;\n        output += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText(source) + '</pre></td></tr>';\n      }\n\n      output += '</table>';\n\n      runLoggingCallbacks('log', QUnit, details);\n\n      config.current.assertions.push({\n        result: false,\n        message: output,\n      });\n    },\n\n    url: function (params) {\n      params = extend(extend({}, QUnit.urlParams), params);\n      var key,\n        querystring = '?';\n\n      for (key in params) {\n        if (!hasOwn.call(params, key)) {\n          continue;\n        }\n        querystring += encodeURIComponent(key) + '=' + encodeURIComponent(params[key]) + '&';\n      }\n      return window.location.pathname + querystring.slice(0, -1);\n    },\n\n    extend: extend,\n    id: id,\n    addEvent: addEvent,\n    // load, equiv, jsDump, diff: Attached later\n  });\n\n  /**\n   * @deprecated: Created for backwards compatibility with test runner that set the hook function\n   * into QUnit.{hook}, instead of invoking it and passing the hook function.\n   * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.\n   * Doing this allows us to tell if the following methods have been overwritten on the actual\n   * QUnit object.\n   */\n  extend(QUnit.constructor.prototype, {\n    // Logging callbacks; all receive a single argument with the listed properties\n    // run test/logs.html for any related changes\n    begin: registerLoggingCallback('begin'),\n\n    // done: { failed, passed, total, runtime }\n    done: registerLoggingCallback('done'),\n\n    // log: { result, actual, expected, message }\n    log: registerLoggingCallback('log'),\n\n    // testStart: { name }\n    testStart: registerLoggingCallback('testStart'),\n\n    // testDone: { name, failed, passed, total }\n    testDone: registerLoggingCallback('testDone'),\n\n    // moduleStart: { name }\n    moduleStart: registerLoggingCallback('moduleStart'),\n\n    // moduleDone: { name, failed, passed, total }\n    moduleDone: registerLoggingCallback('moduleDone'),\n  });\n\n  if (typeof document === 'undefined' || document.readyState === 'complete') {\n    config.autorun = true;\n  }\n\n  QUnit.load = function () {\n    runLoggingCallbacks('begin', QUnit, {});\n\n    // Initialize the config, saving the execution queue\n    var banner,\n      filter,\n      i,\n      label,\n      len,\n      main,\n      ol,\n      toolbar,\n      userAgent,\n      val,\n      urlConfigCheckboxes,\n      moduleFilter,\n      numModules = 0,\n      moduleFilterHtml = '',\n      urlConfigHtml = '',\n      oldconfig = extend({}, config);\n\n    QUnit.init();\n    extend(config, oldconfig);\n\n    config.blocking = false;\n\n    len = config.urlConfig.length;\n\n    for (i = 0; i < len; i++) {\n      val = config.urlConfig[i];\n      if (typeof val === 'string') {\n        val = {\n          id: val,\n          label: val,\n          tooltip: '[no tooltip available]',\n        };\n      }\n      config[val.id] = QUnit.urlParams[val.id];\n      urlConfigHtml += \"<input id='qunit-urlconfig-\" + val.id + \"' name='\" + val.id + \"' type='checkbox'\" + (config[val.id] ? \" checked='checked'\" : '') + \" title='\" + val.tooltip + \"'><label for='qunit-urlconfig-\" + val.id + \"' title='\" + val.tooltip + \"'>\" + val.label + '</label>';\n    }\n\n    moduleFilterHtml += \"<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' \" + (config.module === undefined ? 'selected' : '') + '>< All Modules ></option>';\n    for (i in config.modules) {\n      if (config.modules.hasOwnProperty(i)) {\n        numModules += 1;\n        moduleFilterHtml += \"<option value='\" + encodeURIComponent(i) + \"' \" + (config.module === i ? 'selected' : '') + '>' + i + '</option>';\n      }\n    }\n    moduleFilterHtml += '</select>';\n\n    // `userAgent` initialized at top of scope\n    userAgent = id('qunit-userAgent');\n    if (userAgent) {\n      userAgent.innerHTML = navigator.userAgent;\n    }\n\n    // `banner` initialized at top of scope\n    banner = id('qunit-header');\n    if (banner) {\n      banner.innerHTML = \"<a href='\" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + \"'>\" + banner.innerHTML + '</a> ';\n    }\n\n    // `toolbar` initialized at top of scope\n    toolbar = id('qunit-testrunner-toolbar');\n    if (toolbar) {\n      // `filter` initialized at top of scope\n      filter = document.createElement('input');\n      filter.type = 'checkbox';\n      filter.id = 'qunit-filter-pass';\n\n      addEvent(filter, 'click', function () {\n        var tmp,\n          ol = document.getElementById('qunit-tests');\n\n        if (filter.checked) {\n          ol.className = ol.className + ' hidepass';\n        } else {\n          tmp = ' ' + ol.className.replace(/[\\n\\t\\r]/g, ' ') + ' ';\n          ol.className = tmp.replace(/ hidepass /, ' ');\n        }\n        if (defined.sessionStorage) {\n          if (filter.checked) {\n            sessionStorage.setItem('qunit-filter-passed-tests', 'true');\n          } else {\n            sessionStorage.removeItem('qunit-filter-passed-tests');\n          }\n        }\n      });\n\n      if (config.hidepassed || (defined.sessionStorage && sessionStorage.getItem('qunit-filter-passed-tests'))) {\n        filter.checked = true;\n        // `ol` initialized at top of scope\n        ol = document.getElementById('qunit-tests');\n        ol.className = ol.className + ' hidepass';\n      }\n      toolbar.appendChild(filter);\n\n      // `label` initialized at top of scope\n      label = document.createElement('label');\n      label.setAttribute('for', 'qunit-filter-pass');\n      label.setAttribute('title', 'Only show tests and assertons that fail. Stored in sessionStorage.');\n      label.innerHTML = 'Hide passed tests';\n      toolbar.appendChild(label);\n\n      urlConfigCheckboxes = document.createElement('span');\n      urlConfigCheckboxes.innerHTML = urlConfigHtml;\n      addEvent(urlConfigCheckboxes, 'change', function (event) {\n        var params = {};\n        params[event.target.name] = event.target.checked ? true : undefined;\n        window.location = QUnit.url(params);\n      });\n      toolbar.appendChild(urlConfigCheckboxes);\n\n      if (numModules > 1) {\n        moduleFilter = document.createElement('span');\n        moduleFilter.setAttribute('id', 'qunit-modulefilter-container');\n        moduleFilter.innerHTML = moduleFilterHtml;\n        addEvent(moduleFilter, 'change', function () {\n          var selectBox = moduleFilter.getElementsByTagName('select')[0],\n            selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);\n\n          window.location = QUnit.url({ module: selectedModule === '' ? undefined : selectedModule });\n        });\n        toolbar.appendChild(moduleFilter);\n      }\n    }\n\n    // `main` initialized at top of scope\n    main = id('qunit-fixture');\n    if (main) {\n      config.fixture = main.innerHTML;\n    }\n\n    if (config.autostart) {\n      QUnit.start();\n    }\n  };\n\n  addEvent(window, 'load', QUnit.load);\n\n  // `onErrorFnPrev` initialized at top of scope\n  // Preserve other handlers\n  onErrorFnPrev = window.onerror;\n\n  // Cover uncaught exceptions\n  // Returning true will surpress the default browser handler,\n  // returning false will let it run.\n  window.onerror = function (error, filePath, linerNr) {\n    var ret = false;\n    if (onErrorFnPrev) {\n      ret = onErrorFnPrev(error, filePath, linerNr);\n    }\n\n    // Treat return value as window.onerror itself does,\n    // Only do our handling if not surpressed.\n    if (ret !== true) {\n      if (QUnit.config.current) {\n        if (QUnit.config.current.ignoreGlobalErrors) {\n          return true;\n        }\n        QUnit.pushFailure(error, filePath + ':' + linerNr);\n      } else {\n        QUnit.test(\n          'global failure',\n          extend(\n            function () {\n              QUnit.pushFailure(error, filePath + ':' + linerNr);\n            },\n            { validTest: validTest }\n          )\n        );\n      }\n      return false;\n    }\n\n    return ret;\n  };\n\n  function done() {\n    config.autorun = true;\n\n    // Log the last module results\n    if (config.currentModule) {\n      runLoggingCallbacks('moduleDone', QUnit, {\n        name: config.currentModule,\n        failed: config.moduleStats.bad,\n        passed: config.moduleStats.all - config.moduleStats.bad,\n        total: config.moduleStats.all,\n      });\n    }\n\n    var i,\n      key,\n      banner = id('qunit-banner'),\n      tests = id('qunit-tests'),\n      runtime = +new Date() - config.started,\n      passed = config.stats.all - config.stats.bad,\n      html = ['Tests completed in ', runtime, ' milliseconds.<br/>', \"<span class='passed'>\", passed, \"</span> tests of <span class='total'>\", config.stats.all, \"</span> passed, <span class='failed'>\", config.stats.bad, '</span> failed.'].join('');\n\n    if (banner) {\n      banner.className = config.stats.bad ? 'qunit-fail' : 'qunit-pass';\n    }\n\n    if (tests) {\n      id('qunit-testresult').innerHTML = html;\n    }\n\n    if (config.altertitle && typeof document !== 'undefined' && document.title) {\n      // show ✖ for good, ✔ for bad suite result in title\n      // use escape sequences in case file gets loaded with non-utf-8-charset\n      document.title = [config.stats.bad ? '\\u2716' : '\\u2714', document.title.replace(/^[\\u2714\\u2716] /i, '')].join(' ');\n    }\n\n    // clear own sessionStorage items if all tests passed\n    if (config.reorder && defined.sessionStorage && config.stats.bad === 0) {\n      // `key` & `i` initialized at top of scope\n      for (i = 0; i < sessionStorage.length; i++) {\n        key = sessionStorage.key(i++);\n        if (key.indexOf('qunit-test-') === 0) {\n          sessionStorage.removeItem(key);\n        }\n      }\n    }\n\n    // scroll back to top to show results\n    if (window.scrollTo) {\n      window.scrollTo(0, 0);\n    }\n\n    runLoggingCallbacks('done', QUnit, {\n      failed: config.stats.bad,\n      passed: passed,\n      total: config.stats.all,\n      runtime: runtime,\n    });\n  }\n\n  /** @return Boolean: true if this test should be ran */\n  function validTest(test) {\n    var include,\n      filter = config.filter && config.filter.toLowerCase(),\n      module = config.module && config.module.toLowerCase(),\n      fullName = (test.module + ': ' + test.testName).toLowerCase();\n\n    // Internally-generated tests are always valid\n    if (test.callback && test.callback.validTest === validTest) {\n      delete test.callback.validTest;\n      return true;\n    }\n\n    if (config.testNumber) {\n      return test.testNumber === config.testNumber;\n    }\n\n    if (module && (!test.module || test.module.toLowerCase() !== module)) {\n      return false;\n    }\n\n    if (!filter) {\n      return true;\n    }\n\n    include = filter.charAt(0) !== '!';\n    if (!include) {\n      filter = filter.slice(1);\n    }\n\n    // If the filter matches, we need to honour include\n    if (fullName.indexOf(filter) !== -1) {\n      return include;\n    }\n\n    // Otherwise, do the opposite\n    return !include;\n  }\n\n  // so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n  // Later Safari and IE10 are supposed to support error.stack as well\n  // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\n  function extractStacktrace(e, offset) {\n    offset = offset === undefined ? 3 : offset;\n\n    var stack, include, i, regex;\n\n    if (e.stacktrace) {\n      // Opera\n      return e.stacktrace.split('\\n')[offset + 3];\n    } else if (e.stack) {\n      // Firefox, Chrome\n      stack = e.stack.split('\\n');\n      if (/^error$/i.test(stack[0])) {\n        stack.shift();\n      }\n      if (fileName) {\n        include = [];\n        for (i = offset; i < stack.length; i++) {\n          if (stack[i].indexOf(fileName) != -1) {\n            break;\n          }\n          include.push(stack[i]);\n        }\n        if (include.length) {\n          return include.join('\\n');\n        }\n      }\n      return stack[offset];\n    } else if (e.sourceURL) {\n      // Safari, PhantomJS\n      // hopefully one day Safari provides actual stacktraces\n      // exclude useless self-reference for generated Error objects\n      if (/qunit.js$/.test(e.sourceURL)) {\n        return;\n      }\n      // for actual exceptions, this is useful\n      return e.sourceURL + ':' + e.line;\n    }\n  }\n  function sourceFromStacktrace(offset) {\n    try {\n      throw new Error();\n    } catch (e) {\n      return extractStacktrace(e, offset);\n    }\n  }\n\n  function escapeInnerText(s) {\n    if (!s) {\n      return '';\n    }\n    s = s + '';\n    return s.replace(/[\\&<>]/g, function (s) {\n      switch (s) {\n        case '&':\n          return '&amp;';\n        case '<':\n          return '&lt;';\n        case '>':\n          return '&gt;';\n        default:\n          return s;\n      }\n    });\n  }\n\n  function synchronize(callback, last) {\n    config.queue.push(callback);\n\n    if (config.autorun && !config.blocking) {\n      process(last);\n    }\n  }\n\n  function process(last) {\n    function next() {\n      process(last);\n    }\n    var start = new Date().getTime();\n    config.depth = config.depth ? config.depth + 1 : 1;\n\n    while (config.queue.length && !config.blocking) {\n      if (!defined.setTimeout || config.updateRate <= 0 || new Date().getTime() - start < config.updateRate) {\n        config.queue.shift()();\n      } else {\n        window.setTimeout(next, 13);\n        break;\n      }\n    }\n    config.depth--;\n    if (last && !config.blocking && !config.queue.length && config.depth === 0) {\n      done();\n    }\n  }\n\n  function saveGlobal() {\n    config.pollution = [];\n\n    if (config.noglobals) {\n      for (var key in window) {\n        // in Opera sometimes DOM element ids show up here, ignore them\n        if (!hasOwn.call(window, key) || /^qunit-test-output/.test(key)) {\n          continue;\n        }\n        config.pollution.push(key);\n      }\n    }\n  }\n\n  function checkPollution(name) {\n    var newGlobals,\n      deletedGlobals,\n      old = config.pollution;\n\n    saveGlobal();\n\n    newGlobals = diff(config.pollution, old);\n    if (newGlobals.length > 0) {\n      QUnit.pushFailure('Introduced global variable(s): ' + newGlobals.join(', '));\n    }\n\n    deletedGlobals = diff(old, config.pollution);\n    if (deletedGlobals.length > 0) {\n      QUnit.pushFailure('Deleted global variable(s): ' + deletedGlobals.join(', '));\n    }\n  }\n\n  // returns a new Array with the elements that are in a but not in b\n  function diff(a, b) {\n    var i,\n      j,\n      result = a.slice();\n\n    for (i = 0; i < result.length; i++) {\n      for (j = 0; j < b.length; j++) {\n        if (result[i] === b[j]) {\n          result.splice(i, 1);\n          i--;\n          break;\n        }\n      }\n    }\n    return result;\n  }\n\n  function extend(a, b) {\n    for (var prop in b) {\n      if (b[prop] === undefined) {\n        delete a[prop];\n\n        // Avoid \"Member not found\" error in IE8 caused by setting window.constructor\n      } else if (prop !== 'constructor' || a !== window) {\n        a[prop] = b[prop];\n      }\n    }\n\n    return a;\n  }\n\n  function addEvent(elem, type, fn) {\n    if (elem.addEventListener) {\n      elem.addEventListener(type, fn, false);\n    } else if (elem.attachEvent) {\n      elem.attachEvent('on' + type, fn);\n    } else {\n      fn();\n    }\n  }\n\n  function id(name) {\n    return !!(typeof document !== 'undefined' && document && document.getElementById) && document.getElementById(name);\n  }\n\n  function registerLoggingCallback(key) {\n    return function (callback) {\n      config[key].push(callback);\n    };\n  }\n\n  // Supports deprecated method of completely overwriting logging callbacks\n  function runLoggingCallbacks(key, scope, args) {\n    //debugger;\n    var i, callbacks;\n    if (QUnit.hasOwnProperty(key)) {\n      QUnit[key].call(scope, args);\n    } else {\n      callbacks = config[key];\n      for (i = 0; i < callbacks.length; i++) {\n        callbacks[i].call(scope, args);\n      }\n    }\n  }\n\n  // Test for equality any JavaScript type.\n  // Author: Philippe Rathé <prathe@gmail.com>\n  QUnit.equiv = (function () {\n    // Call the o related callback with the given arguments.\n    function bindCallbacks(o, callbacks, args) {\n      var prop = QUnit.objectType(o);\n      if (prop) {\n        if (QUnit.objectType(callbacks[prop]) === 'function') {\n          return callbacks[prop].apply(callbacks, args);\n        } else {\n          return callbacks[prop]; // or undefined\n        }\n      }\n    }\n\n    // the real equiv function\n    var innerEquiv,\n      // stack to decide between skip/abort functions\n      callers = [],\n      // stack to avoiding loops from circular referencing\n      parents = [],\n      getProto =\n        Object.getPrototypeOf ||\n        function (obj) {\n          return obj.__proto__;\n        },\n      callbacks = (function () {\n        // for string, boolean, number and null\n        function useStrictEquality(b, a) {\n          if (b instanceof a.constructor || a instanceof b.constructor) {\n            // to catch short annotaion VS 'new' annotation of a\n            // declaration\n            // e.g. var i = 1;\n            // var j = new Number(1);\n            return a == b;\n          } else {\n            return a === b;\n          }\n        }\n\n        return {\n          string: useStrictEquality,\n          boolean: useStrictEquality,\n          number: useStrictEquality,\n          null: useStrictEquality,\n          undefined: useStrictEquality,\n\n          nan: function (b) {\n            return isNaN(b);\n          },\n\n          date: function (b, a) {\n            return QUnit.objectType(b) === 'date' && a.valueOf() === b.valueOf();\n          },\n\n          regexp: function (b, a) {\n            return (\n              QUnit.objectType(b) === 'regexp' &&\n              // the regex itself\n              a.source === b.source &&\n              // and its modifers\n              a.global === b.global &&\n              // (gmi) ...\n              a.ignoreCase === b.ignoreCase &&\n              a.multiline === b.multiline &&\n              a.sticky === b.sticky\n            );\n          },\n\n          // - skip when the property is a method of an instance (OOP)\n          // - abort otherwise,\n          // initial === would have catch identical references anyway\n          function: function () {\n            var caller = callers[callers.length - 1];\n            return caller !== Object && typeof caller !== 'undefined';\n          },\n\n          array: function (b, a) {\n            var i, j, len, loop;\n\n            // b could be an object literal here\n            if (QUnit.objectType(b) !== 'array') {\n              return false;\n            }\n\n            len = a.length;\n            if (len !== b.length) {\n              // safe and faster\n              return false;\n            }\n\n            // track reference to avoid circular references\n            parents.push(a);\n            for (i = 0; i < len; i++) {\n              loop = false;\n              for (j = 0; j < parents.length; j++) {\n                if (parents[j] === a[i]) {\n                  loop = true; // dont rewalk array\n                }\n              }\n              if (!loop && !innerEquiv(a[i], b[i])) {\n                parents.pop();\n                return false;\n              }\n            }\n            parents.pop();\n            return true;\n          },\n\n          object: function (b, a) {\n            var i,\n              j,\n              loop,\n              // Default to true\n              eq = true,\n              aProperties = [],\n              bProperties = [];\n\n            // comparing constructors is more strict than using\n            // instanceof\n            if (a.constructor !== b.constructor) {\n              // Allow objects with no prototype to be equivalent to\n              // objects with Object as their constructor.\n              if (!((getProto(a) === null && getProto(b) === Object.prototype) || (getProto(b) === null && getProto(a) === Object.prototype))) {\n                return false;\n              }\n            }\n\n            // stack constructor before traversing properties\n            callers.push(a.constructor);\n            // track reference to avoid circular references\n            parents.push(a);\n\n            for (i in a) {\n              // be strict: don't ensures hasOwnProperty\n              // and go deep\n              loop = false;\n              for (j = 0; j < parents.length; j++) {\n                if (parents[j] === a[i]) {\n                  // don't go down the same path twice\n                  loop = true;\n                }\n              }\n              aProperties.push(i); // collect a's properties\n\n              if (!loop && !innerEquiv(a[i], b[i])) {\n                eq = false;\n                break;\n              }\n            }\n\n            callers.pop(); // unstack, we are done\n            parents.pop();\n\n            for (i in b) {\n              bProperties.push(i); // collect b's properties\n            }\n\n            // Ensures identical properties name\n            return eq && innerEquiv(aProperties.sort(), bProperties.sort());\n          },\n        };\n      })();\n\n    innerEquiv = function () {\n      // can take multiple arguments\n      var args = [].slice.apply(arguments);\n      if (args.length < 2) {\n        return true; // end transition\n      }\n\n      return (\n        (function (a, b) {\n          if (a === b) {\n            return true; // catch the most you can\n          } else if (a === null || b === null || typeof a === 'undefined' || typeof b === 'undefined' || QUnit.objectType(a) !== QUnit.objectType(b)) {\n            return false; // don't lose time with error prone cases\n          } else {\n            return bindCallbacks(a, callbacks, [b, a]);\n          }\n\n          // apply transition with (1..n) arguments\n        })(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length - 1))\n      );\n    };\n\n    return innerEquiv;\n  })();\n\n  /**\n   * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n   * http://flesler.blogspot.com Licensed under BSD\n   * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n   *\n   * @projectDescription Advanced and extensible data dumping for Javascript.\n   * @version 1.0.0\n   * @author Ariel Flesler\n   * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n   */\n  QUnit.jsDump = (function () {\n    function quote(str) {\n      return '\"' + str.toString().replace(/\"/g, '\\\\\"') + '\"';\n    }\n    function literal(o) {\n      return o + '';\n    }\n    function join(pre, arr, post) {\n      var s = jsDump.separator(),\n        base = jsDump.indent(),\n        inner = jsDump.indent(1);\n      if (arr.join) {\n        arr = arr.join(',' + s + inner);\n      }\n      if (!arr) {\n        return pre + post;\n      }\n      return [pre, inner + arr, base + post].join(s);\n    }\n    function array(arr, stack) {\n      var i = arr.length,\n        ret = new Array(i);\n      this.up();\n      while (i--) {\n        ret[i] = this.parse(arr[i], undefined, stack);\n      }\n      this.down();\n      return join('[', ret, ']');\n    }\n\n    var reName = /^function (\\w+)/,\n      jsDump = {\n        parse: function (obj, type, stack) {\n          //type is used mostly internally, you can fix a (custom)type in advance\n          stack = stack || [];\n          var inStack,\n            res,\n            parser = this.parsers[type || this.typeOf(obj)];\n\n          type = typeof parser;\n          inStack = inArray(obj, stack);\n\n          if (inStack != -1) {\n            return 'recursion(' + (inStack - stack.length) + ')';\n          }\n          //else\n          if (type == 'function') {\n            stack.push(obj);\n            res = parser.call(this, obj, stack);\n            stack.pop();\n            return res;\n          }\n          // else\n          return type == 'string' ? parser : this.parsers.error;\n        },\n        typeOf: function (obj) {\n          var type;\n          if (obj === null) {\n            type = 'null';\n          } else if (typeof obj === 'undefined') {\n            type = 'undefined';\n          } else if (QUnit.is('regexp', obj)) {\n            type = 'regexp';\n          } else if (QUnit.is('date', obj)) {\n            type = 'date';\n          } else if (QUnit.is('function', obj)) {\n            type = 'function';\n          } else if (typeof obj.setInterval !== undefined && typeof obj.document !== 'undefined' && typeof obj.nodeType === 'undefined') {\n            type = 'window';\n          } else if (obj.nodeType === 9) {\n            type = 'document';\n          } else if (obj.nodeType) {\n            type = 'node';\n          } else if (\n            // native arrays\n            toString.call(obj) === '[object Array]' ||\n            // NodeList objects\n            (typeof obj.length === 'number' && typeof obj.item !== 'undefined' && (obj.length ? obj.item(0) === obj[0] : obj.item(0) === null && typeof obj[0] === 'undefined'))\n          ) {\n            type = 'array';\n          } else {\n            type = typeof obj;\n          }\n          return type;\n        },\n        separator: function () {\n          return this.multiline ? (this.HTML ? '<br />' : '\\n') : this.HTML ? '&nbsp;' : ' ';\n        },\n        indent: function (extra) {\n          // extra can be a number, shortcut for increasing-calling-decreasing\n          if (!this.multiline) {\n            return '';\n          }\n          var chr = this.indentChar;\n          if (this.HTML) {\n            chr = chr.replace(/\\t/g, '   ').replace(/ /g, '&nbsp;');\n          }\n          return new Array(this._depth_ + (extra || 0)).join(chr);\n        },\n        up: function (a) {\n          this._depth_ += a || 1;\n        },\n        down: function (a) {\n          this._depth_ -= a || 1;\n        },\n        setParser: function (name, parser) {\n          this.parsers[name] = parser;\n        },\n        // The next 3 are exposed so you can use them\n        quote: quote,\n        literal: literal,\n        join: join,\n        //\n        _depth_: 1,\n        // This is the list of parsers, to modify them, use jsDump.setParser\n        parsers: {\n          window: '[Window]',\n          document: '[Document]',\n          error: '[ERROR]', //when no parser is found, shouldn\"t happen\n          unknown: '[Unknown]',\n          null: 'null',\n          undefined: 'undefined',\n          function: function (fn) {\n            var ret = 'function',\n              name = 'name' in fn ? fn.name : (reName.exec(fn) || [])[1]; //functions never have name in IE\n\n            if (name) {\n              ret += ' ' + name;\n            }\n            ret += '( ';\n\n            ret = [ret, QUnit.jsDump.parse(fn, 'functionArgs'), '){'].join('');\n            return join(ret, QUnit.jsDump.parse(fn, 'functionCode'), '}');\n          },\n          array: array,\n          nodelist: array,\n          arguments: array,\n          object: function (map, stack) {\n            var ret = [],\n              keys,\n              key,\n              val,\n              i;\n            QUnit.jsDump.up();\n            if (Object.keys) {\n              keys = Object.keys(map);\n            } else {\n              keys = [];\n              for (key in map) {\n                keys.push(key);\n              }\n            }\n            keys.sort();\n            for (i = 0; i < keys.length; i++) {\n              key = keys[i];\n              val = map[key];\n              ret.push(QUnit.jsDump.parse(key, 'key') + ': ' + QUnit.jsDump.parse(val, undefined, stack));\n            }\n            QUnit.jsDump.down();\n            return join('{', ret, '}');\n          },\n          node: function (node) {\n            var a,\n              val,\n              open = QUnit.jsDump.HTML ? '&lt;' : '<',\n              close = QUnit.jsDump.HTML ? '&gt;' : '>',\n              tag = node.nodeName.toLowerCase(),\n              ret = open + tag;\n\n            for (a in QUnit.jsDump.DOMAttrs) {\n              val = node[QUnit.jsDump.DOMAttrs[a]];\n              if (val) {\n                ret += ' ' + a + '=' + QUnit.jsDump.parse(val, 'attribute');\n              }\n            }\n            return ret + close + open + '/' + tag + close;\n          },\n          functionArgs: function (fn) {\n            //function calls it internally, it's the arguments part of the function\n            var args,\n              l = fn.length;\n\n            if (!l) {\n              return '';\n            }\n\n            args = new Array(l);\n            while (l--) {\n              args[l] = String.fromCharCode(97 + l); //97 is 'a'\n            }\n            return ' ' + args.join(', ') + ' ';\n          },\n          key: quote, //object calls it internally, the key part of an item in a map\n          functionCode: '[code]', //function calls it internally, it's the content of the function\n          attribute: quote, //node calls it internally, it's an html attribute value\n          string: quote,\n          date: quote,\n          regexp: literal, //regex\n          number: literal,\n          boolean: literal,\n        },\n        DOMAttrs: {\n          //attributes to dump from nodes, name=>realName\n          id: 'id',\n          name: 'name',\n          class: 'className',\n        },\n        HTML: false, //if true, entities are escaped ( <, >, \\t, space and \\n )\n        indentChar: '  ', //indentation unit\n        multiline: true, //if true, items in a collection, are separated by a \\n, else just a space.\n      };\n\n    return jsDump;\n  })();\n\n  // from Sizzle.js\n  function getText(elems) {\n    var i,\n      elem,\n      ret = '';\n\n    for (i = 0; elems[i]; i++) {\n      elem = elems[i];\n\n      // Get the text from text nodes and CDATA nodes\n      if (elem.nodeType === 3 || elem.nodeType === 4) {\n        ret += elem.nodeValue;\n\n        // Traverse everything else, except comment nodes\n      } else if (elem.nodeType !== 8) {\n        ret += getText(elem.childNodes);\n      }\n    }\n\n    return ret;\n  }\n\n  // from jquery.js\n  function inArray(elem, array) {\n    if (array.indexOf) {\n      return array.indexOf(elem);\n    }\n\n    for (var i = 0, length = array.length; i < length; i++) {\n      if (array[i] === elem) {\n        return i;\n      }\n    }\n\n    return -1;\n  }\n\n  /*\n   * Javascript Diff Algorithm\n   *  By John Resig (http://ejohn.org/)\n   *  Modified by Chu Alan \"sprite\"\n   *\n   * Released under the MIT license.\n   *\n   * More Info:\n   *  http://ejohn.org/projects/javascript-diff-algorithm/\n   *\n   * Usage: QUnit.diff(expected, actual)\n   *\n   * QUnit.diff( \"the quick brown fox jumped over\", \"the quick fox jumps over\" ) == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n   */\n  QUnit.diff = (function () {\n    function diff(o, n) {\n      var i,\n        ns = {},\n        os = {};\n\n      for (i = 0; i < n.length; i++) {\n        if (ns[n[i]] == null) {\n          ns[n[i]] = {\n            rows: [],\n            o: null,\n          };\n        }\n        ns[n[i]].rows.push(i);\n      }\n\n      for (i = 0; i < o.length; i++) {\n        if (os[o[i]] == null) {\n          os[o[i]] = {\n            rows: [],\n            n: null,\n          };\n        }\n        os[o[i]].rows.push(i);\n      }\n\n      for (i in ns) {\n        if (!hasOwn.call(ns, i)) {\n          continue;\n        }\n        if (ns[i].rows.length == 1 && typeof os[i] != 'undefined' && os[i].rows.length == 1) {\n          n[ns[i].rows[0]] = {\n            text: n[ns[i].rows[0]],\n            row: os[i].rows[0],\n          };\n          o[os[i].rows[0]] = {\n            text: o[os[i].rows[0]],\n            row: ns[i].rows[0],\n          };\n        }\n      }\n\n      for (i = 0; i < n.length - 1; i++) {\n        if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) {\n          n[i + 1] = {\n            text: n[i + 1],\n            row: n[i].row + 1,\n          };\n          o[n[i].row + 1] = {\n            text: o[n[i].row + 1],\n            row: i + 1,\n          };\n        }\n      }\n\n      for (i = n.length - 1; i > 0; i--) {\n        if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && n[i - 1] == o[n[i].row - 1]) {\n          n[i - 1] = {\n            text: n[i - 1],\n            row: n[i].row - 1,\n          };\n          o[n[i].row - 1] = {\n            text: o[n[i].row - 1],\n            row: i - 1,\n          };\n        }\n      }\n\n      return {\n        o: o,\n        n: n,\n      };\n    }\n\n    return function (o, n) {\n      o = o.replace(/\\s+$/, '');\n      n = n.replace(/\\s+$/, '');\n\n      var i,\n        pre,\n        str = '',\n        out = diff(o === '' ? [] : o.split(/\\s+/), n === '' ? [] : n.split(/\\s+/)),\n        oSpace = o.match(/\\s+/g),\n        nSpace = n.match(/\\s+/g);\n\n      if (oSpace == null) {\n        oSpace = [' '];\n      } else {\n        oSpace.push(' ');\n      }\n\n      if (nSpace == null) {\n        nSpace = [' '];\n      } else {\n        nSpace.push(' ');\n      }\n\n      if (out.n.length === 0) {\n        for (i = 0; i < out.o.length; i++) {\n          str += '<del>' + out.o[i] + oSpace[i] + '</del>';\n        }\n      } else {\n        if (out.n[0].text == null) {\n          for (n = 0; n < out.o.length && out.o[n].text == null; n++) {\n            str += '<del>' + out.o[n] + oSpace[n] + '</del>';\n          }\n        }\n\n        for (i = 0; i < out.n.length; i++) {\n          if (out.n[i].text == null) {\n            str += '<ins>' + out.n[i] + nSpace[i] + '</ins>';\n          } else {\n            // `pre` initialized at top of scope\n            pre = '';\n\n            for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {\n              pre += '<del>' + out.o[n] + oSpace[n] + '</del>';\n            }\n            str += ' ' + out.n[i].text + nSpace[i] + pre;\n          }\n        }\n      }\n\n      return str;\n    };\n  })();\n\n  // for CommonJS enviroments, export everything\n  if (typeof exports !== 'undefined') {\n    extend(exports, QUnit);\n  }\n\n  // get at whatever the global object is, like window in browsers\n})(\n  function () {\n    return this;\n  }.call()\n);\n"
  },
  {
    "path": "examples/qunit/package.json",
    "content": "{\n  \"name\": \"yadda-qunit-example\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/qunit/test.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>QUnit Example</title>\n    <link rel=\"stylesheet\" href=\"./lib/qunit-1.10.0.css\" />\n    <script src=\"../../dist/yadda-2.2.0.js\"></script>\n    <script src=\"./lib/qunit-1.10.0.js\"></script>\n    <script src=\"./bottles-library.js\"></script>\n    <script type=\"text/javascript\">\n      var Yadda = require('yadda');\n      var FeatureParser = Yadda.parsers.FeatureParser;\n\n      function runTests() {\n        var text = document.getElementById('scenarios').innerText;\n        var scenarios = new FeatureParser().parse(text).scenarios;\n        for (var i = 0; i < scenarios.length; i++) {\n          var scenario = scenarios[i];\n          test(scenario.title, buildTest(scenario));\n\n          function buildTest(scenario) {\n            return function () {\n              Yadda.createInstance(library).run(scenario.steps);\n            };\n          }\n        }\n      }\n    </script>\n  </head>\n  <body onLoad=\"runTests()\">\n    <div id=\"qunit\"></div>\n    <pre id=\"scenarios\">\n    Scenario: A bottle falls from the wall\n\n        Given 100 green bottles are standing on the wall\n        when 1 green bottle accidentally falls\n        then there are 99 green bottles standing on the wall\n\n    Scenario: No bottles are left\n\n        Given 1 green bottles are standing on the wall\n        when 1 green bottle accidentally falls\n        then there are 0 green bottles standing on the wall\n  </pre\n    >\n  </body>\n</html>\n"
  },
  {
    "path": "examples/report-unused-steps/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/report-unused-steps\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/report-unused-steps/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/report-unused-steps/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/report-unused-steps/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/report-unused-steps/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\n\nmodule.exports = (function () {\n  var wall;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n  var library = English.library(dictionary)\n\n    .given('An unused step')\n\n    .given(['Another unused step', 'Yet $another unused step'])\n\n    .given('a $NUM foot wall', function (height, next) {\n      wall = new Wall();\n      next();\n    })\n\n    .given('$NUM green bottles are standing on the wall', function (number_of_bottles, next) {\n      wall.bottles = number_of_bottles;\n      next();\n    })\n\n    .when('$NUM green bottle accidentally falls', function (number_of_falling_bottles, next) {\n      wall.fall(number_of_falling_bottles);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM green bottles standing on the wall', function (number_of_bottles, next) {\n      assert.equal(number_of_bottles, wall.bottles);\n      next();\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/report-unused-steps/features/bottles.feature",
    "content": "Feature: Mocha Asynchronous Example\n\nBackground:\n\n    Given a 6 foot wall\n\nScenario: A bottle falls from the wall\n\n    Given 100 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 99 green bottles standing on the wall\n\nScenario: No bottles are left\n\n    Given 1 green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are 0 green bottles standing on the wall\n\n@Todo\nScenario: Bottles are reset\n\n    Given there are no green bottles\n    when 5 minutes has elapsed\n    then there are 100 green bottles standing on the wall\n\nScenario: [N] bottles are standing on a wall\n\n    Given [N] green bottles are standing on the wall\n    when 1 green bottle accidentally falls\n    then there are [N-1] green bottles standing on the wall\n\n    Where:\n        N   | N-1\n        100 | 99\n        99  | 98\n        10  | 9\n"
  },
  {
    "path": "examples/report-unused-steps/package.json",
    "content": "{\n  \"name\": \"yadda-report-unused-steps-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/report-unused-steps/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nvar EventBus = Yadda.EventBus;\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nvar unused = {};\n\nEventBus.instance()\n  .on(EventBus.ON_DEFINE, function (event) {\n    unused[event.data.pattern] = event.data.signature;\n  })\n  .on(EventBus.ON_EXECUTE, function (event) {\n    delete unused[event.data.pattern];\n  });\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, done);\n      });\n    });\n  });\n});\n\nafter(function () {\n  console.log('Unused steps');\n  for (var pattern in unused) {\n    console.log(pattern);\n  }\n});\n"
  },
  {
    "path": "examples/resuable-scenarios/README.md",
    "content": "```\nnpm install\nnpm link\ncd examples/resuable-scenarios\nnpm install\nnpm test\n```\n"
  },
  {
    "path": "examples/resuable-scenarios/bin/example.bat",
    "content": "@echo off\nsetlocal\n\n:run\nnode_modules\\.bin\\mocha --reporter spec test.js\nendlocal"
  },
  {
    "path": "examples/resuable-scenarios/bin/example.js",
    "content": "'use strict';\n\nvar spawn = require('child_process').spawn;\nvar platform = require('os').platform();\nvar cmd = /^win/.test(platform) ? 'bin\\\\example.bat' : 'bin/example.sh';\nspawn(cmd, [], { stdio: 'inherit' }).on('exit', function (code) {\n  process.exit(code);\n});\n"
  },
  {
    "path": "examples/resuable-scenarios/bin/example.sh",
    "content": "#!/bin/bash\n\n./node_modules/.bin/mocha --reporter spec test.js"
  },
  {
    "path": "examples/resuable-scenarios/bottles-library.js",
    "content": "'use strict';\n\nvar Yadda = require('yadda');\nvar English = Yadda.localisation.English;\nvar Dictionary = Yadda.Dictionary;\nvar assert = require('assert');\nvar format = require('util').format;\n\nmodule.exports = (function () {\n  var wall;\n  var dictionary = new Dictionary().define('NUM', /(\\d+)/);\n  var library = English.library(dictionary)\n\n    .define('Sing $NUM $COLOUR bottles', function (number_of_bottles, colour, next) {\n      this.yadda.run([format('Given %d %s bottles are standing on the wall', number_of_bottles, colour), format('When 1 %s bottle accidentally falls', colour), format('Then there are %d %s bottles standing on the wall', number_of_bottles - 1, colour)], next);\n    })\n\n    .given('$NUM $COLOUR bottles are standing on the wall', function (number_of_bottles, colour, next) {\n      wall = wall || new Wall();\n      wall.bottles = number_of_bottles;\n      wall.bottleColour = colour;\n      next();\n    })\n\n    .when('$NUM $COLOUR bottle accidentally falls', function (number_of_falling_bottles, colour, next) {\n      wall.fall(number_of_falling_bottles);\n      next();\n    })\n\n    .then('there (?:are|are still) $NUM $COLOUR bottles standing on the wall', function (number_of_bottles, colour, next) {\n      assert.equal(number_of_bottles, wall.bottles);\n      next();\n    });\n\n  var Wall = function (bottles) {\n    this.bottles = bottles;\n    this.fall = function (n) {\n      this.bottles -= n;\n    };\n    this.returned = function () {\n      this.bottles++;\n    };\n  };\n\n  return library;\n})();\n"
  },
  {
    "path": "examples/resuable-scenarios/features/bottles.feature",
    "content": "Feature: Reusable Scenario Example\n\nScenario: 100 green bottles\n\n    Sing 100 green bottles are standing on the wall\n\n\nScenario: 100 blue bottles\n\n    Sing 100 blue bottles are standing on the wall\n\n\n\n"
  },
  {
    "path": "examples/resuable-scenarios/package.json",
    "content": "{\n  \"name\": \"yadda-context-example\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"npm --loglevel error link yadda\",\n    \"test\": \"node bin/example.js\"\n  },\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache2\"\n}\n"
  },
  {
    "path": "examples/resuable-scenarios/test.js",
    "content": "/* jslint node: true */\n/* global featureFile, scenarios, steps */\n'use strict';\n\nvar Yadda = require('yadda');\nYadda.plugins.mocha.StepLevelPlugin.init();\n\nnew Yadda.FeatureFileSearch('features').each(function (file) {\n  featureFile(file, function (feature) {\n    var library = require('./bottles-library');\n    var yadda = Yadda.createInstance(library);\n\n    scenarios(feature.scenarios, function (scenario) {\n      var ctx = { yadda: yadda };\n      steps(scenario.steps, function (step, done) {\n        yadda.run(step, ctx, done);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "karma.conf.js",
    "content": "/* jslint node: false */\n\nmodule.exports = function (config) {\n  'use strict';\n  config.set({\n    plugins: ['karma-browserify', 'karma-phantomjs-launcher', 'karma-mocha'],\n    frameworks: ['browserify', 'mocha'],\n    files: ['lib/**/*.js', { pattern: 'lib/**/!(*.js)', included: false }, 'test/**/*.js', { pattern: 'test/**/!(*.js)', included: false }],\n    preprocessors: {\n      'lib/**/*.js': ['browserify'],\n      'test/**/*.js': ['browserify'],\n    },\n    client: {\n      mocha: {\n        reporter: 'html',\n        ui: 'bdd',\n      },\n    },\n    browserify: {\n      debug: true,\n      configure: function (bundle) {\n        bundle.on('prebundle', function () {\n          bundle.require('./lib/index', { expose: 'yadda' });\n        });\n      },\n    },\n    browsers: ['PhantomJS'],\n    reporters: ['progress'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: false,\n    captureTimeout: 6000,\n    singleRun: true,\n  });\n};\n"
  },
  {
    "path": "lib/Array.js",
    "content": "'use strict';\n\nvar fn = require('./fn');\n\nmodule.exports = function (obj) {\n  function ensure_array(obj) {\n    var array = obj ? [].concat(obj) : [];\n    array.in_array = fn.curry(array, in_array, array);\n    array.each = fn.curry(array, each, array);\n    array.each_async = fn.curry(array, each_async, array);\n    array.collect = fn.curry(array, collect, array);\n    array.collect_async = fn.curry(array, collect_async, array);\n    array.flatten = fn.curry(array, flatten, array);\n    array.inject = fn.curry(array, inject, array);\n    array.push_all = fn.curry(array, push_all, array);\n    array.fill = fn.curry(array, fill, array);\n    array.find_all = fn.curry(array, find_all, array);\n    array.find = fn.curry(array, find, array);\n    array.last = fn.curry(array, last, array);\n    array.naked = fn.curry(array, naked, array);\n    return array;\n  }\n\n  function is_array(obj) {\n    return Object.prototype.toString.call(obj) === '[object Array]';\n  }\n\n  function in_array(items, item) {\n    for (var i = 0; i < items.length; i++) {\n      if (items[i] === item) {\n        return true;\n      }\n    }\n  }\n\n  function flatten(items) {\n    if (!is_array(items)) return [items];\n    if (items.length === 0) return items;\n    var head = flatten(items[0]);\n    var tail = flatten(items.slice(1));\n    return ensure_array(head.concat(tail));\n  }\n\n  function each(items, iterator) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(items[i], i);\n    }\n    return result;\n  }\n\n  function each_async(items, iterator, callback) {\n    callback = callback || fn.noop;\n    if (!items.length) return callback();\n    var index = 0;\n    var iterate = function () {\n      iterator(items[index], index, function (err, result) {\n        if (err) return callback(err);\n        if (++index >= items.length) return callback(null, result);\n        iterate();\n      });\n    };\n    iterate();\n  }\n\n  function collect(items, iterator) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      results.push(iterator(items[i], i));\n    }\n    return results;\n  }\n\n  function collect_async(items, iterator, callback) {\n    var results = ensure_array();\n    each_async(\n      items,\n      function (item, index, each_callback) {\n        iterator(item, index, function (err) {\n          if (err) return each_callback(err);\n          results.push_all(Array.prototype.splice.call(arguments, 1));\n          each_callback();\n        });\n      },\n      function (err) {\n        if (err) return callback(err);\n        callback(null, results);\n      }\n    );\n  }\n\n  function inject(items, default_value, iterator) {\n    var result = default_value;\n    for (var i = 0; i < items.length; i++) {\n      result = iterator(result, items[i]);\n    }\n    return result;\n  }\n\n  function push_all(items, more_items) {\n    more_items = more_items ? [].concat(more_items) : [];\n    for (var i = 0; i < more_items.length; i++) {\n      items.push(more_items[i]);\n    }\n    return items;\n  }\n\n  function fill(items, item, num) {\n    for (var i = 0; i < num; i++) {\n      items.push(item);\n    }\n    return items;\n  }\n\n  function find_all(items, test) {\n    var results = ensure_array();\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        results.push(items[i]);\n      }\n    }\n    return results;\n  }\n\n  function find(items, test) {\n    var result;\n    for (var i = 0; i < items.length; i++) {\n      if (test(items[i], i)) {\n        result = items[i];\n        break;\n      }\n    }\n    return result;\n  }\n\n  function last(items) {\n    return items[items.length - 1];\n  }\n\n  function naked(items) {\n    return [].concat(items);\n  }\n\n  return ensure_array(obj);\n};\n"
  },
  {
    "path": "lib/Competition.js",
    "content": "'use strict';\n\nvar LevenshteinDistanceScore = require('./scores/LevenshteinDistanceScore');\nvar SameLibraryScore = require('./scores/SameLibraryScore');\nvar MultiScore = require('./scores/MultiScore');\nvar $ = require('./Array');\n\n// Understands appropriateness of macros in relation to a specific step\nvar Competition = function (step, macros, last_macro) {\n  var results = [];\n\n  this.validate = function () {\n    if (is_undefined()) return { step: step, valid: false, reason: 'Undefined Step' };\n    if (is_ambiguous()) return { step: step, valid: false, reason: 'Ambiguous Step (Patterns [' + winning_patterns() + '] are all equally good candidates)' };\n    return { step: step, valid: true, winner: this.winner() };\n  };\n\n  this.clear_winner = function () {\n    if (is_undefined()) throw new Error('Undefined Step: [' + step + ']');\n    if (is_ambiguous()) throw new Error('Ambiguous Step: [' + step + ']. Patterns [' + winning_patterns() + '] match equally well.');\n    return this.winner();\n  };\n\n  function is_undefined() {\n    return results.length === 0;\n  }\n\n  function is_ambiguous() {\n    return results.length > 1 && results[0].score.equals(results[1].score);\n  }\n\n  this.winner = function () {\n    return results[0].macro;\n  };\n\n  function winning_patterns() {\n    return results.find_all(by_winning_score).collect(macro_signatures).join(', ');\n  }\n\n  function rank(step, macros) {\n    results = macros\n      .collect(function (macro) {\n        return {\n          macro: macro,\n          score: new MultiScore([new LevenshteinDistanceScore(step, macro.levenshtein_signature()), new SameLibraryScore(macro, last_macro)]),\n        };\n      })\n      .sort(by_ascending_score);\n  }\n\n  function by_ascending_score(a, b) {\n    return b.score.compare(a.score);\n  }\n\n  function by_winning_score(result) {\n    return result.score.equals(results[0].score);\n  }\n\n  function macro_signatures(result) {\n    return result.macro.toString();\n  }\n\n  rank(step, $(macros));\n};\n\nmodule.exports = Competition;\n"
  },
  {
    "path": "lib/Context.js",
    "content": "'use strict';\n\n// Constructs an object that macros will be bound to before execution\nvar Context = function (properties) {\n  // I was previously getting some weird errors using instanceof to determine if\n  // the \"other\" object was a context object. Using pTFUHht733hM6wfnruGLgAu6Uqvy7MVp instead\n  this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp = true;\n  this.properties = {};\n\n  this.merge = function (other) {\n    if (other && other.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp) return this.merge(other.properties);\n    return new Context(this.properties)._merge(other);\n  };\n\n  this._merge = function (other) {\n    for (var key in other) {\n      this.properties[key] = other[key];\n    }\n    return this;\n  };\n\n  this._merge(properties);\n};\n\nmodule.exports = Context;\n"
  },
  {
    "path": "lib/Dictionary.js",
    "content": "'use strict';\n\nvar $ = require('./Array');\nvar RegularExpression = require('./RegularExpression');\nvar pass_through_converter = require('./converters/pass-through-converter');\n\n// Understands term definitions\nvar Dictionary = function (prefix) {\n  // eslint-disable-next-line no-redeclare\n  var prefix = prefix || '$';\n  var definitions = {};\n  var term_grouping_pattern = new RegularExpression(new RegExp('(?:^|[^\\\\\\\\])\\\\' + prefix + '(\\\\w+)', 'g'));\n  var term_splitting_pattern = new RegExp('(\\\\' + prefix + '\\\\w+)');\n  var _this = this;\n\n  this.define = function (term, pattern, converters) {\n    if (is_defined(term)) throw new Error('Duplicate term: [' + term + ']');\n    if (converters && is_expandable(pattern)) throw new Error('Expandable terms cannot use converters: [' + term + ']');\n    if (converters && !is_compatible(converters, pattern)) throw new Error('Wrong number of converters for: [' + term + ']');\n\n    if (!is_expandable(pattern) && !converters) converters = get_matching_group_converters(pattern);\n    definitions[term] = { pattern: normalise(pattern), converters: $(converters) };\n    return this;\n  };\n\n  this.merge = function (other) {\n    if (other._prefix() !== this._prefix()) throw new Error('Cannot merge dictionaries with different prefixes');\n    return new Dictionary(prefix)._merge(this)._merge(other);\n  };\n\n  this._merge = function (other) {\n    other.each(function (term, definition) {\n      _this.define(term, definition.pattern);\n    });\n    return this;\n  };\n\n  this._prefix = function () {\n    return prefix;\n  };\n\n  this.each = function (callback) {\n    for (var term in definitions) {\n      callback(term, definitions[term]);\n    }\n  };\n\n  this.expand = function (signature, already_expanding) {\n    var text = normalise(signature);\n    return is_expandable(text) ? { pattern: expand_sub_terms(text, $(already_expanding)), converters: get_converters(text) } : { pattern: text, converters: get_converters(text) };\n  };\n\n  function expand_sub_terms(text, already_expanding) {\n    return get_sub_terms(text).each(function (sub_term) {\n      if (already_expanding.in_array(sub_term)) throw new Error('Circular Definition: [' + already_expanding.join(', ') + ']');\n      var sub_term_grouping_pattern = expand_sub_term(sub_term, already_expanding);\n      text = text.replace(prefix + sub_term, sub_term_grouping_pattern);\n      return text;\n    });\n  }\n\n  function get_sub_terms(text) {\n    return term_grouping_pattern.groups(text);\n  }\n\n  function expand_sub_term(sub_term, already_expanding) {\n    var pattern = definitions[sub_term] ? definitions[sub_term].pattern : '(.+)';\n    return is_expandable(pattern) ? _this.expand(pattern, already_expanding.concat(sub_term)).pattern : pattern;\n  }\n\n  function normalise(pattern) {\n    return pattern.toString().replace(/^\\/|\\/$/g, '');\n  }\n\n  function is_defined(term) {\n    return !!definitions[term];\n  }\n\n  function is_expandable(text) {\n    return term_grouping_pattern.test(text);\n  }\n\n  function is_compatible(converters, pattern) {\n    return count_converter_arguments(converters) === count_matching_groups(pattern);\n  }\n\n  function get_converters(text) {\n    return $(text.split(term_splitting_pattern)).inject($(), function (converters, fragment) {\n      return converters.push_all(is_expandable(fragment) ? get_sub_term_converters(fragment) : get_matching_group_converters(fragment));\n    });\n  }\n\n  function get_matching_group_converters(text) {\n    return $().fill(pass_through_converter, count_matching_groups(text));\n  }\n\n  function get_sub_term_converters(text) {\n    return get_sub_terms(text).inject($(), function (converters, sub_term) {\n      return is_defined(sub_term) ? converters.push_all(definitions[sub_term].converters) : converters.push_all(get_converters(expand_sub_term(sub_term, [])));\n    });\n  }\n\n  function count_matching_groups(pattern) {\n    return new RegExp(pattern + '|').exec('').length - 1;\n  }\n\n  function count_converter_arguments(converters) {\n    return $(converters).inject(0, function (sum, converter) {\n      return sum + converter.length - 1;\n    });\n  }\n};\n\nmodule.exports = Dictionary;\n"
  },
  {
    "path": "lib/EventBus.js",
    "content": "'use strict';\n\nvar $ = require('./Array');\nvar fn = require('./fn');\nvar event_bus = new EventBus();\n\n// A communication channel between event emitters and event listeners\nfunction EventBus() {\n  var event_handlers = $();\n\n  this.send = function (event_name, event_data, next) {\n    if (arguments.length === 1) return this.send(event_name, {});\n    if (arguments.length === 2 && fn.is_function(event_data)) return this.send(event_name, {}, event_data);\n    notify_handlers(event_name, event_data);\n    next && next();\n    return this;\n  };\n\n  this.on = function (event_pattern, callback) {\n    event_handlers.push({ pattern: event_pattern, callback: callback });\n    return this;\n  };\n\n  var notify_handlers = function (event_name, event_data) {\n    find_handlers(event_name).each(function (callback) {\n      callback({ name: event_name, data: event_data });\n    });\n  };\n\n  var find_handlers = function (event_name) {\n    return event_handlers\n      .find_all(function (handler) {\n        return new RegExp(handler.pattern).test(event_name);\n      })\n      .collect(function (handler) {\n        return handler.callback;\n      });\n  };\n}\n\nfunction instance() {\n  return event_bus;\n}\n\nmodule.exports = {\n  instance: instance,\n  ON_SCENARIO: '__ON_SCENARIO__',\n  ON_STEP: '__ON_STEP__',\n  ON_EXECUTE: '__ON_EXECUTE__',\n  ON_DEFINE: '__ON_DEFINE__',\n};\n"
  },
  {
    "path": "lib/FeatureFileSearch.js",
    "content": "'use strict';\n\nvar FileSearch = require('./FileSearch');\n\nvar FeatureFileSearch = function (directories) {\n  this.constructor(directories, /.*\\.(?:feature|spec|specification)$/);\n};\nFeatureFileSearch.prototype = new FileSearch();\n\nmodule.exports = FeatureFileSearch;\n"
  },
  {
    "path": "lib/FileSearch.js",
    "content": "'use strict';\n\nvar shims = require('./shims/index');\nvar path = shims.path;\nvar fs = shims.fs;\nvar $ = require('./Array');\n\n// Searches for files in the given directories and their sub-directories, matching at least one of the given patterns\nvar FileSearch = function (directories, patterns) {\n  // eslint-disable-next-line no-redeclare\n  var patterns = patterns || /.*/;\n\n  this.each = function (fn) {\n    this.list().forEach(fn);\n  };\n\n  this.list = function () {\n    return $(directories).inject($(), function (files, directory) {\n      return files.concat(list_files(directory).find_all(by_pattern));\n    });\n  };\n\n  var list_files = function (directory) {\n    return $(list_immediate_files(directory).concat(list_sub_directory_files(directory)));\n  };\n\n  var list_immediate_files = function (directory) {\n    return ls(directory).find_all(by_file);\n  };\n\n  var list_sub_directory_files = function (directory) {\n    return ls(directory)\n      .find_all(by_directory)\n      .inject($(), function (files, directory) {\n        return files.concat(list_files(directory));\n      });\n  };\n\n  var ls = function (directory) {\n    if (!fs.existsSync(directory)) return $();\n    return $(fs.readdirSync(directory)).collect(function (file) {\n      return path.join(directory, file);\n    });\n  };\n\n  var by_file = function (file) {\n    return !by_directory(file);\n  };\n\n  var by_directory = function (file) {\n    return fs.statSync(file).isDirectory();\n  };\n\n  var by_pattern = function (filename) {\n    return $(patterns).find(function (pattern) {\n      return new RegExp(pattern).test(filename);\n    });\n  };\n};\n\nmodule.exports = FileSearch;\n"
  },
  {
    "path": "lib/Interpreter.js",
    "content": "'use strict';\n\nvar Competition = require('./Competition');\nvar Context = require('./Context');\nvar EventBus = require('./EventBus');\nvar $ = require('./Array');\nvar fn = require('./fn');\n\n// Understands a scenario\nvar Interpreter = function (libraries) {\n  // eslint-disable-next-line no-redeclare\n  var libraries = $(libraries);\n  var event_bus = EventBus.instance();\n  var last_macro;\n  var _this = this;\n\n  this.requires = function (libs) {\n    libraries.push_all(libs);\n    return this;\n  };\n\n  this.validate = function (scenario) {\n    var results = $(scenario).collect(function (step) {\n      var report = _this.rank_macros(step).validate();\n      last_macro = report.winner;\n      return report;\n    });\n    if (results.find(by_invalid_step)) throw new Error('Scenario cannot be interpreted\\n' + results.collect(validation_report).join('\\n'));\n  };\n\n  function by_invalid_step(result) {\n    return !result.valid;\n  }\n\n  function validation_report(result) {\n    return result.step + (result.valid ? '' : ' <-- ' + result.reason);\n  }\n\n  this.interpret = function (scenario, scenario_context, next) {\n    scenario_context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_SCENARIO, { scenario: scenario, ctx: scenario_context.properties });\n    var iterator = make_step_iterator(scenario_context, next);\n    $(scenario).each_async(iterator, next);\n  };\n\n  var make_step_iterator = function (scenario_context, next) {\n    var iterator = function (step, index, callback) {\n      _this.interpret_step(step, scenario_context, callback);\n    };\n    return next ? iterator : fn.asynchronize(null, iterator);\n  };\n\n  this.interpret_step = function (step, scenario_context, next) {\n    var context = new Context().merge(scenario_context);\n    event_bus.send(EventBus.ON_STEP, { step: step, ctx: context.properties });\n    var macro = this.rank_macros(step).clear_winner();\n    last_macro = macro;\n    macro.interpret(step, context || {}, next);\n  };\n\n  this.rank_macros = function (step) {\n    return new Competition(step, compatible_macros(step), last_macro);\n  };\n\n  var compatible_macros = function (step) {\n    return libraries.inject([], function (macros, library) {\n      return macros.concat(library.find_compatible_macros(step));\n    });\n  };\n};\n\nmodule.exports = Interpreter;\n"
  },
  {
    "path": "lib/Library.js",
    "content": "'use strict';\n\nvar Macro = require('./Macro');\nvar Dictionary = require('./Dictionary');\nvar $ = require('./Array');\n\n// Understands how to index macros\nvar Library = function (dictionary) {\n  // eslint-disable-next-line no-redeclare\n  var dictionary = dictionary || new Dictionary();\n  var macros = $();\n  var _this = this;\n\n  this.define = function (signatures, fn, macro_context, options) {\n    $(signatures).each(function (signature) {\n      define_macro(signature, fn, macro_context, options);\n    });\n    return this;\n  };\n\n  var define_macro = function (signature, fn, macro_context, options) {\n    if (_this.get_macro(signature)) throw new Error('Duplicate macro: [' + signature + ']');\n    macros.push(new Macro(signature, dictionary.expand(signature), fn, macro_context, _this, options));\n  };\n\n  this.get_macro = function (signature) {\n    return macros.find(function (other_macro) {\n      return other_macro.is_identified_by(signature);\n    });\n  };\n\n  this.find_compatible_macros = function (step) {\n    return macros.find_all(function (macro) {\n      return macro.can_interpret(step);\n    });\n  };\n};\n\nmodule.exports = Library;\n"
  },
  {
    "path": "lib/Macro.js",
    "content": "'use strict';\n\nvar fn = require('./fn');\nvar $ = require('./Array');\nvar Context = require('./Context');\nvar RegularExpression = require('./RegularExpression');\nvar EventBus = require('./EventBus');\n\n// Understands how to invoke a step\nvar Macro = function (signature, parsed_signature, macro, macro_context, library, options) {\n  /* eslint-disable no-redeclare */\n  var signature = normalise(signature);\n  var signature_pattern = new RegularExpression(parsed_signature.pattern);\n  var macro = macro || fn.async_noop;\n  var event_bus = EventBus.instance();\n  var options = options || {};\n  /* eslint-enable no-redeclare */\n\n  this.library = library;\n\n  this.is_identified_by = function (other_signature) {\n    return signature === normalise(other_signature);\n  };\n\n  this.can_interpret = function (step) {\n    return signature_pattern.test(step);\n  };\n\n  this.interpret = function (step, scenario_context, next) {\n    var context = new Context({ step: step }).merge(macro_context).merge(scenario_context);\n    convert(signature_pattern.groups(step), function (err, args) {\n      if (err) return next(err);\n      event_bus.send(EventBus.ON_EXECUTE, { step: step, ctx: context.properties, pattern: signature_pattern.toString(), args: args });\n      var result;\n      try {\n        result = fn.invoke(macro, context.properties, is_sync(args) ? args : args.concat(next));\n      } catch (err) {\n        if (next) return next(err);\n        throw err;\n      }\n      if (is_promise(result)) return result.then(fn.noargs(next)).catch(next);\n      if (is_sync(args)) return next && next();\n    });\n  };\n\n  this.is_sibling = function (other_macro) {\n    return other_macro && other_macro.defined_in(library);\n  };\n\n  this.defined_in = function (other_library) {\n    return library === other_library;\n  };\n\n  this.levenshtein_signature = function () {\n    return signature_pattern.without_expressions();\n  };\n\n  this.toString = function () {\n    return signature;\n  };\n\n  function is_promise(result) {\n    if (options.mode) return options.mode === 'promise';\n    return result && result.then;\n  }\n\n  function is_sync(args) {\n    if (options.mode) return options.mode === 'sync';\n    return macro !== fn.async_noop && macro.length !== args.length + 1;\n  }\n\n  function normalise(signature) {\n    return new RegExp(signature).toString();\n  }\n\n  function convert(args, next) {\n    var index = 0;\n    return $(parsed_signature.converters)\n      .collect(function (converter) {\n        return function (callback) {\n          converter.apply(null, args.slice(index, (index += converter.length - 1)).concat(callback));\n        };\n      })\n      .collect_async(function (converter, index, callback) {\n        converter(callback);\n      }, next);\n  }\n\n  event_bus.send(EventBus.ON_DEFINE, { signature: signature, pattern: signature_pattern.toString() });\n};\n\nmodule.exports = Macro;\n"
  },
  {
    "path": "lib/Platform.js",
    "content": "'use strict';\n\nmodule.exports = Platform;\n\nfunction Platform() {\n  function get_container() {\n    /* eslint-disable no-undef */\n    if (is_browser()) return window;\n    if (is_phantom()) return phantom;\n    if (is_node()) return global;\n    /* eslint-enable no-undef */\n  }\n\n  function is_node() {\n    return typeof process !== 'undefined' && typeof global !== 'undefined' && typeof __dirname !== 'undefined';\n  }\n\n  function is_browser() {\n    return typeof window !== 'undefined';\n  }\n\n  function is_phantom() {\n    return typeof phantom !== 'undefined';\n  }\n\n  function is_karma() {\n    return typeof window !== 'undefined' && typeof window.__karma__ !== 'undefined';\n  }\n\n  return {\n    get_container: get_container,\n    is_node: is_node,\n    is_browser: is_browser,\n    is_phantom: is_phantom,\n    is_karma: is_karma,\n  };\n}\n"
  },
  {
    "path": "lib/RegularExpression.js",
    "content": "'use strict';\n\nvar $ = require('./Array');\n\n// Wrapper for JavaScript Regular Expressions\nvar RegularExpression = function (pattern_or_regexp) {\n  var groups_pattern = /(^|[^\\\\\\\\])\\(.*?\\)/g;\n  var sets_pattern = /(^|[^\\\\\\\\])\\[.*?\\]/g;\n  var repetitions_pattern = /(^|[^\\\\\\\\])\\{.*?\\}/g;\n  var regex_aliases_pattern = /(^|[^\\\\\\\\])\\\\./g;\n  var non_word_tokens_pattern = /[^\\w\\s]/g;\n  var regexp = new RegExp(pattern_or_regexp);\n\n  this.test = function (text) {\n    var result = regexp.test(text);\n    this.reset();\n    return result;\n  };\n\n  this.groups = function (text) {\n    var results = $();\n    var match = regexp.exec(text);\n    while (match) {\n      var groups = match.slice(1, match.length);\n      results.push(groups);\n      match = regexp.global && regexp.exec(text);\n    }\n    this.reset();\n    return results.flatten();\n  };\n\n  this.reset = function () {\n    regexp.lastIndex = 0;\n    return this;\n  };\n\n  this.without_expressions = function () {\n    return regexp.source.replace(groups_pattern, '$1').replace(sets_pattern, '$1').replace(repetitions_pattern, '$1').replace(regex_aliases_pattern, '$1').replace(non_word_tokens_pattern, '');\n  };\n\n  this.equals = function (other) {\n    return this.toString() === other.toString();\n  };\n\n  this.toString = function () {\n    return '/' + regexp.source + '/';\n  };\n};\n\nmodule.exports = RegularExpression;\n"
  },
  {
    "path": "lib/StringUtils.js",
    "content": "'use strict';\n\nmodule.exports = {\n  trim: function trim(text) {\n    return text.replace(/^\\s+|\\s+$/g, '');\n  },\n  rtrim: function rtrim(text) {\n    return text.replace(/\\s+$/g, '');\n  },\n  isBlank: function isBlank(text) {\n    return /^\\s*$/g.test(text);\n  },\n  isNotBlank: function isNotBlank(text) {\n    return !this.isBlank(text);\n  },\n  indentation: function indentation(text) {\n    var match = /^(\\s*)/.exec(text);\n    return (match && match[0].length) || 0;\n  },\n};\n"
  },
  {
    "path": "lib/Yadda.js",
    "content": "/*jslint node: true */\n'use strict';\n\nvar Interpreter = require('./Interpreter');\nvar Context = require('./Context');\nvar fn = require('./fn');\n\nvar Yadda = function (libraries, interpreter_context) {\n  if (!(this instanceof Yadda)) {\n    return new Yadda(libraries, interpreter_context);\n  }\n\n  this.interpreter = new Interpreter(libraries);\n\n  this.requires = function (libraries) {\n    this.interpreter.requires(libraries);\n    return this;\n  };\n\n  this.yadda = function (scenario, scenario_context, next) {\n    if (arguments.length === 0) return this;\n    if (arguments.length === 2 && fn.is_function(scenario_context)) return this.yadda(scenario, {}, scenario_context);\n    this.interpreter.validate(scenario);\n    this.interpreter.interpret(scenario, new Context().merge(interpreter_context).merge(scenario_context), next);\n  };\n\n  // Not everyone shares my sense of humour re the recursive api :(\n  // See https://github.com/acuminous/yadda/issues/111\n  this.run = this.yadda;\n\n  this.toString = function () {\n    return 'Yadda 2.2.0 Copyright 2010 Stephen Cresswell';\n  };\n};\n\nmodule.exports = Yadda;\n"
  },
  {
    "path": "lib/converters/date-converter.js",
    "content": "'use strict';\n\nmodule.exports = function date_converter(value, next) {\n  var converted = Date.parse(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a date'));\n  return next(null, new Date(converted));\n};\n"
  },
  {
    "path": "lib/converters/float-converter.js",
    "content": "'use strict';\n\nmodule.exports = function float_converter(value, next) {\n  var converted = parseFloat(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to a float'));\n  return next(null, converted);\n};\n"
  },
  {
    "path": "lib/converters/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  date: require('./date-converter'),\n  integer: require('./integer-converter'),\n  float: require('./float-converter'),\n  list: require('./list-converter'),\n  table: require('./table-converter'),\n  pass_through: require('./pass-through-converter'),\n};\n"
  },
  {
    "path": "lib/converters/integer-converter.js",
    "content": "'use strict';\n\nmodule.exports = function integer_converter(value, next) {\n  var converted = parseInt(value);\n  if (isNaN(converted)) return next(new Error('Cannot convert [' + value + '] to an integer'));\n  return next(null, converted);\n};\n"
  },
  {
    "path": "lib/converters/list-converter.js",
    "content": "'use strict';\n\nmodule.exports = function list_converter(value, next) {\n  return next(null, value.split(/\\n/));\n};\n"
  },
  {
    "path": "lib/converters/pass-through-converter.js",
    "content": "'use strict';\n\nmodule.exports = function pass_through_converter(value, next) {\n  return next(null, value);\n};\n"
  },
  {
    "path": "lib/converters/table-converter.js",
    "content": "'use strict';\n\nvar $ = require('../Array');\nvar StringUtils = require('../StringUtils');\nvar COLUMN_SEPARATOR_REGEX = /[\\|\\u2506]/;\nvar OUTER_BORDERS_REGEX = /^[\\|\\u2506]|[\\|\\u2506]$/g;\nvar DASH_REGEX = /^[\\\\|\\u2506]?-{3,}/;\n\nmodule.exports = function table_converter(value, next) {\n  var rows = value.split(/\\n/);\n  var headings = parse_headings(rows.shift());\n  var handler = is_horizinal_separator(rows[0]) ? handle_multiline_row : handle_single_line_row;\n  var table = $();\n\n  try {\n    $(rows).each(handler);\n    next(null, collapse(table));\n  } catch (err) {\n    next(err);\n  }\n\n  function handle_single_line_row(row) {\n    if (is_horizinal_separator(row)) throw new Error('Dashes are unexpected at this time');\n    start_new_row();\n    parse_fields(row);\n  }\n\n  function handle_multiline_row(row) {\n    if (is_horizinal_separator(row)) return start_new_row();\n    parse_fields(row);\n  }\n\n  function parse_headings(row) {\n    return $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX))\n      .collect(function (value) {\n        return { text: StringUtils.trim(value), indentation: StringUtils.indentation(value) };\n      })\n      .naked();\n  }\n\n  function is_horizinal_separator(row) {\n    return DASH_REGEX.test(row);\n  }\n\n  function start_new_row() {\n    table.push({});\n  }\n\n  function parse_fields(row) {\n    var fields = table.last();\n    $(row.replace(OUTER_BORDERS_REGEX, '').split(COLUMN_SEPARATOR_REGEX)).each(function (field, index) {\n      var column = headings[index].text;\n      var indentation = headings[index].indentation;\n      var text = StringUtils.rtrim(field.substr(indentation));\n      if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n      fields[column] = (fields[column] || []).concat(text);\n    });\n  }\n\n  function collapse(table) {\n    return table\n      .collect(function (row) {\n        var new_row = {};\n        for (var heading in row) {\n          new_row[heading] = row[heading].join('\\n');\n        }\n        return new_row;\n      })\n      .naked();\n  }\n};\n"
  },
  {
    "path": "lib/fn.js",
    "content": "'use strict';\n\nmodule.exports = (function () {\n  var slice = Array.prototype.slice;\n\n  function curry(ctx, fn) {\n    var args = slice.call(arguments, 2);\n    return function () {\n      return fn.apply(ctx, args.concat(slice.call(arguments)));\n    };\n  }\n\n  function invoke(fn, ctx, args) {\n    return fn.apply(ctx, args);\n  }\n\n  function is_function(object) {\n    var getType = {};\n    return object && getType.toString.call(object) === '[object Function]';\n  }\n\n  function noop() {}\n\n  function noargs(fn) {\n    return function () {\n      return fn();\n    };\n  }\n\n  function asynchronize(ctx, fn) {\n    return function () {\n      var next = slice.call(arguments, arguments.length - 1)[0];\n      var args = slice.call(arguments, 0, arguments.length - 2);\n      fn.apply(ctx, args);\n      if (next) next();\n    };\n  }\n\n  return {\n    noop: noop,\n    noargs: noargs,\n    async_noop: asynchronize(null, noop),\n    asynchronize: asynchronize,\n    is_function: is_function,\n    curry: curry,\n    invoke: invoke,\n  };\n})();\n"
  },
  {
    "path": "lib/index.js",
    "content": "'use strict';\n\nvar api = {\n  Yadda: require('./Yadda'),\n  EventBus: require('./EventBus'),\n  Interpreter: require('./Interpreter'),\n  Context: require('./Context'),\n  Library: require('./Library'),\n  Dictionary: require('./Dictionary'),\n  FeatureFileSearch: require('./FeatureFileSearch'),\n  FileSearch: require('./FileSearch'),\n  Platform: require('./Platform'),\n  localisation: require('./localisation/index'),\n  converters: require('./converters/index'),\n  parsers: require('./parsers/index'),\n  plugins: require('./plugins/index'),\n  shims: require('./shims/index'),\n  createInstance: function () {\n    // Not everyone shares my sense of humour re the recursive api :(\n    // See https://github.com/acuminous/yadda/issues/111\n    return api.Yadda.apply(null, Array.prototype.slice.call(arguments, 0));\n  },\n};\n\nmodule.exports = api;\n"
  },
  {
    "path": "lib/localisation/Chinese.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature|功能',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)',\n    examples: '(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)',\n    pending: '(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)',\n    only: '(?:[Oo]nly|仅仅?)',\n    background: '[Bb]ackground|背景|前提',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Chinese', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/Dutch.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)',\n    scenario: '(?:[Ss]cenario|[Gg|eval)',\n    examples: '(?:[Vv]oorbeelden?)',\n    pending: '(?:[Tt]odo|[Mm]oet nog)',\n    only: '(?:[Aa]lleen)',\n    background: '(?:[Aa]chtergrond)',\n    given: '(?:[Ss]tel|[Gg]egeven(?:\\\\sdat)?|[Ee]n|[Mm]aar)',\n    when: '(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)',\n    then: '(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Dutch', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/English.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ff]eature',\n    scenario: '(?:[Ss]cenario|[Ss]cenario [Oo]utline)',\n    examples: '(?:[Ee]xamples|[Ww]here)',\n    pending: '(?:[Pp]ending|[Tt]odo)',\n    only: '(?:[Oo]nly)',\n    background: '[Bb]ackground',\n    given: '(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('English', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/French.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]onctionnalité)',\n    scenario: '(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)',\n    examples: '(?:[Ee]xemples|[Ee]xemple|[Oo][uù])',\n    pending: '(?:[Ee]n attente|[Ee]n cours|[Tt]odo)',\n    only: '(?:[Ss]eulement])',\n    background: '(?:[Cc]ontexte)',\n    given: '(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)',\n    when: \"(?:[Qq]uand|[Ll]orsqu'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)\",\n    then: '(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)',\n\n    _steps: ['given', 'when', 'then', 'soit', 'etantdonnees', 'etantdonnee', 'etantdonne', 'quand', 'lorsque', 'alors'],\n    // Also aliasing French verbs for given-when-then for signature-lookup\n    get soit() {\n      return this.given;\n    },\n    get etantdonnees() {\n      return this.given;\n    },\n    get etantdonnee() {\n      return this.given;\n    },\n    get etantdonne() {\n      return this.given;\n    },\n    get quand() {\n      return this.when;\n    },\n    get lorsque() {\n      return this.when;\n    },\n    get alors() {\n      return this.then;\n    },\n  };\n\n  return new Language('French', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/German.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)',\n    scenario: '(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)',\n    examples: '(?:[Bb]eispiele?)',\n    pending: '(?:[Tt]odo|[Oo]ffen)',\n    only: '(?:[Nn]ur|[Ee]inzig)',\n    background: '(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)',\n    given: '(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)',\n    when: '(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)',\n    then: '(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('German', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/Language.js",
    "content": "'use strict';\n\nvar Library = require('../Library');\nvar $ = require('../Array');\n\nmodule.exports = function (name, vocabulary) {\n  var _this = this;\n\n  // See http://github.com/acuminous/yadda#203\n  this.is_language = true;\n\n  this.library = function (dictionary) {\n    return _this.localise_library(new Library(dictionary));\n  };\n\n  this.localise_library = function (library) {\n    $(vocabulary._steps).each(function (keyword) {\n      library[keyword] = function (signatures, fn, ctx, options) {\n        return $(signatures).each(function (signature) {\n          signature = prefix_signature(_this.localise(keyword), signature);\n          return library.define(signature, fn, ctx, options);\n        });\n      };\n    });\n    return library;\n  };\n\n  var prefix_signature = function (prefix, signature) {\n    var regex_delimiters = new RegExp('^/|/$', 'g');\n    var start_of_signature = new RegExp(/^(?:\\^)?/);\n    var one_or_more_spaces = '\\\\s+';\n    var leading_spaces = '^(?:\\\\s)*';\n    return signature\n      .toString()\n      .replace(regex_delimiters, '')\n      .replace(start_of_signature, leading_spaces + prefix + one_or_more_spaces);\n  };\n\n  this.localise = function (keyword) {\n    if (vocabulary[keyword] === undefined) throw new Error('Keyword \"' + keyword + '\" has not been translated into ' + name + '.');\n    return vocabulary[keyword];\n  };\n};\n"
  },
  {
    "path": "lib/localisation/Norwegian.js",
    "content": "﻿'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '[Ee]genskap',\n    scenario: '[Ss]cenario',\n    examples: '[Ee]ksempler',\n    pending: '[Aa]vventer',\n    only: '[Bb]are',\n    background: '[Bb]akgrunn',\n    given: '(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)',\n    when: '(?:[Nn]år|[Oo]g|[Mm]en)',\n    then: '(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)',\n    _steps: ['given', 'when', 'then', 'gitt', 'når', 'så'],\n    // Also aliasing Norwegian verbs for given-when-then for signature-lookup\n    get gitt() {\n      return this.given;\n    },\n    get når() {\n      return this.when;\n    },\n    get så() {\n      return this.then;\n    },\n  };\n\n  return new Language('Norwegian', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/Pirate.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Tt]ale|[Yy]arn)',\n    scenario: '(?:[Aa]dventure|[Ss]ortie)',\n    examples: '[Ww]herest',\n    pending: '[Bb]rig',\n    only: '[Bb]lack [Ss]pot',\n    background: '[Aa]ftground',\n    given: '(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)',\n    when: '(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)',\n    then: '(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)',\n    _steps: ['given', 'when', 'then', 'giveth', 'whence', 'thence'],\n    // Also aliasing Pirate verbs for given-when-then for signature-lookup\n    get giveth() {\n      return this.given;\n    },\n    get whence() {\n      return this.when;\n    },\n    get thence() {\n      return this.then;\n    },\n  };\n\n  return new Language('Pirate', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/Polish.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)',\n    scenario: '(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)',\n    examples: '[Pp]rzykłady',\n    pending: '(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)',\n    only: '[Tt]ylko',\n    background: '[Zz]ałożenia',\n    given: '(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)',\n    when: '(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)',\n    then: '(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)',\n    _steps: ['given', 'when', 'then', 'zakladajac', 'majac', 'jezeli', 'jesli', 'gdy', 'kiedy', 'wtedy'],\n    // Also aliasing Polish verbs for given-when-then for signature-lookup\n    get zakladajac() {\n      return this.given;\n    },\n    get majac() {\n      return this.given;\n    },\n    get jezeli() {\n      return this.when;\n    },\n    get jesli() {\n      return this.when;\n    },\n    get gdy() {\n      return this.when;\n    },\n    get kiedy() {\n      return this.when;\n    },\n    get wtedy() {\n      return this.then;\n    },\n  };\n\n  return new Language('Polish', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/Portuguese.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)',\n    scenario: '(?:[Cc]en[aá]rio|[Cc]aso)',\n    examples: '(?:[Ee]xemplos|[Ee]xemplo)',\n    pending: '[Pp]endente',\n    only: '[S][óo]',\n    background: '[Ff]undo',\n    given: '(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)',\n    when: '(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)',\n    then: '(?:[Ee]nt[aã]o|[Ee]|[Mm]as)',\n\n    _steps: ['given', 'when', 'then', 'seja', 'sejam', 'dado', 'dada', 'dados', 'dadas', 'quando', 'se', 'entao'],\n\n    get seja() {\n      return this.given;\n    },\n    get sejam() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get quando() {\n      return this.when;\n    },\n    get se() {\n      return this.when;\n    },\n    get entao() {\n      return this.then;\n    },\n  };\n\n  return new Language('Portuguese', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/Russian.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)',\n    scenario: 'Сценарий',\n    examples: 'Примеры?',\n    pending: '(?:[Ww]ip|[Tt]odo)',\n    only: 'Только',\n    background: '(?:[Пп]редыстория|[Кк]онтекст)',\n    given: '(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    when: '(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    then: '(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\\\s[Яя])?',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Russian', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/Spanish.js",
    "content": "'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Ff]uncionalidad|[Cc]aracterística)',\n    scenario: '(?:[Ee]scenario|[Cc]aso)',\n    examples: '(?:[Ee]jemplos|[Ee]jemplo)',\n    pending: '[Pp]endiente',\n    only: '[S]ólo',\n    background: '[Ff]ondo',\n    given: '(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)',\n    when: '(?:[Cc]uando|[Ss]i|[Qq]ue)',\n    then: '(?:[Ee]ntonces)',\n\n    _steps: ['given', 'when', 'then', 'sea', 'sean', 'dado', 'dada', 'dados', 'dadas', 'cuando', 'si', 'entonces'],\n\n    get sea() {\n      return this.given;\n    },\n    get sean() {\n      return this.given;\n    },\n    get dado() {\n      return this.given;\n    },\n    get dada() {\n      return this.given;\n    },\n    get dados() {\n      return this.given;\n    },\n    get dadas() {\n      return this.given;\n    },\n    get cuando() {\n      return this.when;\n    },\n    get si() {\n      return this.when;\n    },\n    get entonces() {\n      return this.then;\n    },\n  };\n\n  return new Language('Spanish', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/Ukrainian.js",
    "content": "/**\n * Author: Oleksii Kuznietsov\n * https://github.com/Bloodhound1982\n */\n/* jslint node: true */\n'use strict';\n\nvar Language = require('./Language');\n\nmodule.exports = (function () {\n  var vocabulary = {\n    feature: '(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)',\n    scenario: '(?:[Сс]ценарій|[Шш]аблон)',\n    examples: '[Пп]риклади',\n    pending: '(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)',\n    only: '[Тт]ільки',\n    background: '[Кк]онтекст',\n    given: '(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)',\n    when: '(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)',\n    then: '(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)',\n    _steps: ['given', 'when', 'then'],\n  };\n\n  return new Language('Ukrainian', vocabulary);\n})();\n"
  },
  {
    "path": "lib/localisation/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  Chinese: require('./Chinese'),\n  English: require('./English'),\n  French: require('./French'),\n  German: require('./German'),\n  Dutch: require('./Dutch'),\n  Norwegian: require('./Norwegian'),\n  Pirate: require('./Pirate'),\n  Ukrainian: require('./Ukrainian'),\n  Polish: require('./Polish'),\n  Spanish: require('./Spanish'),\n  Russian: require('./Russian'),\n  Portuguese: require('./Portuguese'),\n  default: require('./English'),\n  Language: require('./Language'),\n};\n"
  },
  {
    "path": "lib/parsers/FeatureFileParser.js",
    "content": "'use strict';\n\nvar FeatureFileParser = function (options) {\n  var fs = require('../shims').fs;\n  var FeatureParser = require('./FeatureParser');\n  var parser = new FeatureParser(options);\n\n  this.parse = function (file, next) {\n    var text = fs.readFileSync(file, 'utf8');\n    var feature = parser.parse(text);\n    return (next && next(feature)) || feature;\n  };\n};\n\nmodule.exports = FeatureFileParser;\n"
  },
  {
    "path": "lib/parsers/FeatureParser.js",
    "content": "'use strict';\n\nvar $ = require('../Array');\nvar fn = require('../fn');\nvar StringUtils = require('../StringUtils');\nvar Localisation = require('../localisation');\n\nvar FeatureParser = function (options) {\n  /* eslint-disable no-redeclare */\n  var defaults = { language: Localisation.default, leftPlaceholderChar: '[', rightPlaceholderChar: ']' };\n  var options = options && options.is_language ? { language: options } : options || defaults;\n  var language = options.language || defaults.language;\n  var left_placeholder_char = options.leftPlaceholderChar || defaults.leftPlaceholderChar;\n  var right_placeholder_char = options.rightPlaceholderChar || defaults.rightPlaceholderChar;\n  /* eslint-enable no-redeclare */\n\n  var FEATURE_REGEX = new RegExp('^\\\\s*' + language.localise('feature') + ':\\\\s*(.*)', 'i');\n  var SCENARIO_REGEX = new RegExp('^\\\\s*' + language.localise('scenario') + ':\\\\s*(.*)', 'i');\n  var BACKGROUND_REGEX = new RegExp('^\\\\s*' + language.localise('background') + ':\\\\s*(.*)', 'i');\n  var EXAMPLES_REGEX = new RegExp('^\\\\s*' + language.localise('examples') + ':', 'i');\n  var TEXT_REGEX = new RegExp('^(.*)$', 'i');\n  var SINGLE_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#');\n  var MULTI_LINE_COMMENT_REGEX = new RegExp('^\\\\s*#{3,}');\n  var BLANK_REGEX = new RegExp('^(\\\\s*)$');\n  var DASH_REGEX = new RegExp('(^\\\\s*[\\\\|\\u2506]?-{3,})');\n  var SIMPLE_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)$');\n  var NVP_ANNOTATION_REGEX = new RegExp('^\\\\s*@([^=]*)=(.*)$');\n\n  var specification;\n  var comment;\n\n  this.parse = function (text, next) {\n    reset();\n    split(text).each(parse_line);\n    return (next && next(specification.export())) || specification.export();\n  };\n\n  function reset() {\n    specification = new Specification();\n    comment = false;\n  }\n\n  function split(text) {\n    return $(text.split(/\\r\\n|\\n/));\n  }\n\n  function parse_line(line, index) {\n    var match;\n    var line_number = index + 1;\n    try {\n      // eslint-disable-next-line no-return-assign\n      if ((match = MULTI_LINE_COMMENT_REGEX.test(line))) return (comment = !comment);\n      if (comment) return;\n      if ((match = SINGLE_LINE_COMMENT_REGEX.test(line))) return;\n      if ((match = SIMPLE_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: true }, line_number);\n      if ((match = NVP_ANNOTATION_REGEX.exec(line))) return specification.handle('Annotation', { key: StringUtils.trim(match[1]), value: StringUtils.trim(match[2]) }, line_number);\n      if ((match = FEATURE_REGEX.exec(line))) return specification.handle('Feature', match[1], line_number);\n      if ((match = SCENARIO_REGEX.exec(line))) return specification.handle('Scenario', match[1], line_number);\n      if ((match = BACKGROUND_REGEX.exec(line))) return specification.handle('Background', match[1], line_number);\n      if ((match = EXAMPLES_REGEX.exec(line))) return specification.handle('Examples', line_number);\n      if ((match = BLANK_REGEX.exec(line))) return specification.handle('Blank', match[0], line_number);\n      if ((match = DASH_REGEX.exec(line))) return specification.handle('Dash', match[1], line_number);\n      if ((match = TEXT_REGEX.exec(line))) return specification.handle('Text', match[1], line_number);\n    } catch (e) {\n      e.message = 'Error parsing line ' + line_number + ', \"' + line + '\".\\nOriginal error was: ' + e.message;\n      throw e;\n    }\n  }\n\n  var Handlers = function (handlers) {\n    // eslint-disable-next-line no-redeclare\n    var handlers = handlers || {};\n\n    this.register = function (event, handler) {\n      handlers[event] = handler;\n    };\n\n    this.unregister = function () {\n      $(Array.prototype.slice.call(arguments)).each(function (event) {\n        delete handlers[event];\n      });\n    };\n\n    this.find = function (event) {\n      if (!handlers[event.toLowerCase()]) throw new Error(event + ' is unexpected at this time');\n      return { handle: handlers[event.toLowerCase()] };\n    };\n  };\n\n  var Specification = function () {\n    var current_element = this;\n    var feature;\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      text: fn.noop,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      feature: start_feature,\n      scenario: start_scenario,\n      background: start_background,\n    });\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function start_feature(event, title) {\n      // eslint-disable-next-line no-return-assign\n      return (feature = new Feature(title, annotations, new Annotations()));\n    }\n\n    function start_scenario(event, title, line_number) {\n      feature = new Feature(title, new Annotations(), annotations);\n      return feature.on(event, title, line_number);\n    }\n\n    var start_background = start_scenario;\n\n    this.handle = function (event, data, line_number) {\n      current_element = current_element.on(event, data, line_number);\n    };\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      if (!feature) throw new Error('A feature must contain one or more scenarios');\n      return feature.export();\n    };\n  };\n\n  var Annotations = function () {\n    var annotations = {};\n\n    this.stash = function (key, value) {\n      if (/\\s/.test(key)) throw new Error('Invalid annotation: ' + key);\n      annotations[key.toLowerCase()] = value;\n    };\n\n    this.export = function () {\n      return annotations;\n    };\n  };\n\n  var Feature = function (title, annotations, stashed_annotations) {\n    var description = [];\n    var scenarios = [];\n    var background = new NullBackground();\n    var handlers = new Handlers({\n      text: capture_description,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n      background: start_background,\n    });\n    var _this = this;\n\n    function start_background(event, title) {\n      background = new Background(title, _this);\n      stashed_annotations = new Annotations();\n      return background;\n    }\n\n    function stash_annotation(event, annotation) {\n      handlers.unregister('background', 'text');\n      stashed_annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_description(event, text) {\n      description.push(StringUtils.trim(text));\n    }\n\n    function start_scenario(event, title) {\n      var scenario = new Scenario(title, background, stashed_annotations, _this);\n      scenarios.push(scenario);\n      stashed_annotations = new Annotations();\n      return scenario;\n    }\n\n    function validate() {\n      if (scenarios.length === 0) throw new Error('Feature requires one or more scenarios');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        scenarios: $(scenarios)\n          .collect(function (scenario) {\n            return scenario.export();\n          })\n          .flatten()\n          .naked(),\n      };\n    };\n  };\n\n  var Background = function (title, feature) {\n    var steps = [];\n    var blanks = [];\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: stash_annotation,\n      scenario: start_scenario,\n    });\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', stash_annotation);\n      handlers.register('scenario', start_scenario);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      validate();\n      return feature.on(event, annotation, line_number);\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Background requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      return {\n        steps: steps,\n      };\n    };\n  };\n\n  var NullBackground = function () {\n    var handlers = new Handlers();\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      return {\n        steps: [],\n      };\n    };\n  };\n\n  var Scenario = function (title, background, annotations, feature) {\n    var description = [];\n    var steps = [];\n    var blanks = [];\n    var examples;\n    var indentation = 0;\n    var handlers = new Handlers({\n      text: capture_step,\n      blank: fn.noop,\n      annotation: start_scenario,\n      scenario: start_scenario,\n      examples: start_examples,\n    });\n    var _this = this;\n\n    function capture_step(event, text, line_number) {\n      handlers.register('dash', enable_multiline_step);\n      steps.push(StringUtils.trim(text));\n    }\n\n    function enable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash', 'annotation', 'scenario', 'examples');\n      handlers.register('text', start_multiline_step);\n      handlers.register('blank', stash_blanks);\n      indentation = StringUtils.indentation(text);\n    }\n\n    function start_multiline_step(event, text, line_number) {\n      handlers.register('dash', disable_multiline_step);\n      handlers.register('text', continue_multiline_step);\n      handlers.register('blank', stash_blanks);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n      handlers.register('examples', start_examples);\n      append_to_step(text, '\\n');\n    }\n\n    function continue_multiline_step(event, text, line_number) {\n      unstash_blanks();\n      append_to_step(text, '\\n');\n    }\n\n    function stash_blanks(event, text, line_number) {\n      blanks.push(text);\n    }\n\n    function unstash_blanks() {\n      if (!blanks.length) return;\n      append_to_step(blanks.join('\\n'), '\\n');\n      blanks = [];\n    }\n\n    function disable_multiline_step(event, text, line_number) {\n      handlers.unregister('dash');\n      handlers.register('text', capture_step);\n      handlers.register('blank', fn.noop);\n      unstash_blanks();\n    }\n\n    function append_to_step(text, prefix) {\n      if (StringUtils.isNotBlank(text) && StringUtils.indentation(text) < indentation) throw new Error('Indentation error');\n      steps[steps.length - 1] = steps[steps.length - 1] + prefix + StringUtils.rtrim(text.substr(indentation));\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return feature.on(event, data, line_number);\n    }\n\n    function start_examples(event, data, line_number) {\n      validate();\n      examples = new Examples(_this);\n      return examples;\n    }\n\n    function validate() {\n      if (steps.length === 0) throw new Error('Scenario requires one or more steps');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.export = function () {\n      validate();\n      var result = {\n        title: title,\n        annotations: annotations.export(),\n        description: description,\n        steps: background.export().steps.concat(steps),\n      };\n      return examples ? examples.expand(result) : result;\n    };\n  };\n\n  var Examples = function (scenario) {\n    var headings = [];\n    var examples = $();\n    var annotations = new Annotations();\n    var handlers = new Handlers({\n      blank: fn.noop,\n      dash: start_example_table,\n      text: capture_headings,\n    });\n\n    function start_example_table(evnet, data, line_number) {\n      handlers.unregister('blank', 'dash');\n    }\n\n    function capture_headings(event, data, line_number) {\n      handlers.register('annotation', stash_annotation);\n      handlers.register('text', capture_singleline_fields);\n      handlers.register('dash', enable_multiline_examples);\n      var pos = 1;\n      headings = split(data)\n        .collect(function (column) {\n          var attributes = { text: StringUtils.trim(column), left: pos, indentation: StringUtils.indentation(column) };\n          pos += column.length + 1;\n          return attributes;\n        })\n        .naked();\n    }\n\n    function stash_annotation(event, annotation, line_number) {\n      handlers.unregister('blank', 'dash');\n      annotations.stash(annotation.key, annotation.value);\n    }\n\n    function capture_singleline_fields(event, data, line_number) {\n      handlers.register('dash', end_example_table);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n      annotations = new Annotations();\n    }\n\n    function enable_multiline_examples(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n    }\n\n    function start_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', continue_capturing_multiline_fields);\n      handlers.register('dash', stop_capturing_multiline_fields);\n      handlers.register('blank', end_example_table);\n      examples.push({ annotations: annotations, fields: parse_fields(data, {}) });\n      add_meta_fields(line_number);\n    }\n\n    function continue_capturing_multiline_fields(event, data, line_number) {\n      parse_fields(data, examples.last().fields);\n    }\n\n    function stop_capturing_multiline_fields(event, data, line_number) {\n      handlers.register('text', start_capturing_multiline_fields);\n      annotations = new Annotations();\n    }\n\n    function end_example_table(event, data, line_number) {\n      handlers.unregister('text', 'dash');\n      handlers.register('blank', fn.noop);\n      handlers.register('annotation', start_scenario);\n      handlers.register('scenario', start_scenario);\n    }\n\n    function add_meta_fields(line_number) {\n      var fields = examples.last().fields;\n      $(headings).each(function (heading) {\n        fields[heading.text + '.index'] = [examples.length];\n        fields[heading.text + '.start.line'] = [line_number];\n        fields[heading.text + '.start.column'] = [heading.left + heading.indentation];\n      });\n    }\n\n    function parse_fields(row, fields) {\n      split(row, headings.length).each(function (field, index) {\n        var column = headings[index].text;\n        var indentation = headings[index].indentation;\n        var text = StringUtils.rtrim(field.substr(indentation));\n        if (StringUtils.isNotBlank(field) && StringUtils.indentation(field) < indentation) throw new Error('Indentation error');\n        fields[column] = (fields[column] || []).concat(text);\n      });\n      return fields;\n    }\n\n    function split(row, number_of_fields) {\n      var separator = row.indexOf('\\u2506') >= 0 ? '\\u2506' : '|';\n      var fields = $(row.split(separator));\n      if (number_of_fields !== undefined && number_of_fields !== fields.length) {\n        throw new Error('Incorrect number of fields in example table. Expected ' + number_of_fields + ' but found ' + fields.length);\n      }\n      return fields;\n    }\n\n    function start_scenario(event, data, line_number) {\n      validate();\n      return scenario.on(event, data, line_number);\n    }\n\n    function validate() {\n      if (headings.length === 0) throw new Error('Examples table requires one or more headings');\n      if (examples.length === 0) throw new Error('Examples table requires one or more rows');\n    }\n\n    this.on = function (event, data, line_number) {\n      return handlers.find(event).handle(event, data, line_number) || this;\n    };\n\n    this.expand = function (scenario) {\n      validate();\n      return examples\n        .collect(function (example) {\n          return {\n            title: substitute(example.fields, scenario.title),\n            annotations: shallow_merge(example.annotations.export(), scenario.annotations),\n            description: substitute_all(example, scenario.description),\n            steps: substitute_all(example.fields, scenario.steps),\n          };\n        })\n        .naked();\n    };\n\n    function shallow_merge() {\n      var result = {};\n      $(Array.prototype.slice.call(arguments)).each(function (annotations) {\n        for (var key in annotations) {\n          result[key] = annotations[key];\n        }\n      });\n      return result;\n    }\n\n    function substitute_all(example, lines) {\n      return $(lines)\n        .collect(function (line) {\n          return substitute(example, line);\n        })\n        .naked();\n    }\n\n    function substitute(example, line) {\n      for (var heading in example) {\n        line = line.replace(new RegExp('\\\\' + left_placeholder_char + '\\\\s*' + heading + '\\\\s*\\\\' + right_placeholder_char, 'g'), StringUtils.rtrim(example[heading].join('\\n')));\n      }\n      return line;\n    }\n  };\n};\n\nmodule.exports = FeatureParser;\n"
  },
  {
    "path": "lib/parsers/StepParser.js",
    "content": "'use strict';\n\nvar $ = require('../Array');\n\nvar StepParser = function () {\n  var NON_BLANK_REGEX = /[^\\s]/;\n\n  this.parse = function (text, next) {\n    var steps = split(text).find_all(non_blanks);\n    return (next && next(steps)) || steps;\n  };\n\n  var split = function (text) {\n    return $(text.split(/\\n/));\n  };\n\n  var non_blanks = function (text) {\n    return text && NON_BLANK_REGEX.test(text);\n  };\n};\n\nmodule.exports = StepParser;\n"
  },
  {
    "path": "lib/parsers/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  StepParser: require('./StepParser'),\n  FeatureParser: require('./FeatureParser'),\n  FeatureFileParser: require('./FeatureFileParser'),\n};\n"
  },
  {
    "path": "lib/plugins/CasperPlugin.js",
    "content": "'use strict';\n\nif (!module.client) {\n  var fs = require('../shims').fs;\n  global.process = global.process || {\n    cwd: function () {\n      return fs.workingDirectory;\n    },\n  };\n}\n\nmodule.exports = function (yadda, casper) {\n  var EventBus = require('yadda').EventBus;\n\n  yadda.interpreter.interpret_step = function (step, ctx, next) {\n    var _this = this;\n    casper.then(function () {\n      casper.test.info(step);\n      EventBus.instance().send(EventBus.ON_STEP, { step: step, ctx: ctx });\n      _this.rank_macros(step).clear_winner().interpret(step, ctx, next);\n    });\n  };\n\n  casper.yadda = function (script, ctx) {\n    if (script === undefined) return this;\n    yadda.run(script, ctx);\n  };\n};\n"
  },
  {
    "path": "lib/plugins/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  casper: require('./CasperPlugin'),\n  mocha: {\n    ScenarioLevelPlugin: require('./mocha/ScenarioLevelPlugin'),\n    StepLevelPlugin: require('./mocha/StepLevelPlugin'),\n  },\n  get jasmine() {\n    return this.mocha;\n  },\n};\n"
  },
  {
    "path": "lib/plugins/mocha/BasePlugin.js",
    "content": "'use strict';\n\nvar Localisation = require('../../localisation');\nvar Platform = require('../../Platform');\nvar FeatureFileParser = require('../../parsers/FeatureFileParser');\nvar $ = require('../../Array');\n\nmodule.exports.create = function (options) {\n  /* jslint shadow: true */\n  var platform = new Platform();\n  var language = options.language || Localisation.default;\n  var parser = options.parser || new FeatureFileParser(options);\n  var container = options.container || platform.get_container();\n\n  function featureFiles(files, iterator) {\n    $(files).each(function (file) {\n      features(parser.parse(file), iterator);\n    });\n  }\n\n  function features(features, iterator) {\n    $(features).each(function (feature) {\n      describe(feature.title, feature, iterator);\n    });\n  }\n\n  function describe(title, subject, iterator) {\n    var _describe = getDescribe(subject.annotations);\n    _describe(title, function () {\n      iterator(subject);\n    });\n  }\n\n  function it_async(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function (done) {\n      iterator(this, subject, done);\n    });\n  }\n\n  function it_sync(title, subject, iterator) {\n    var _it = getIt(subject.annotations);\n    _it(title, function () {\n      iterator(this, subject);\n    });\n  }\n\n  function getIt(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xit;\n    if (has_annotation(annotations, 'only')) return container.it.only || container.fit || container.iit;\n    return container.it;\n  }\n\n  function getDescribe(annotations, next) {\n    if (has_annotation(annotations, 'pending')) return container.xdescribe;\n    if (has_annotation(annotations, 'only')) return container.describe.only || container.fdescribe || container.ddescribe;\n    return container.describe;\n  }\n\n  function has_annotation(annotations, name) {\n    var regexp = new RegExp('^' + language.localise(name) + '$', 'i');\n    for (var key in annotations) {\n      if (regexp.test(key)) return true;\n    }\n  }\n\n  return {\n    featureFiles: featureFiles,\n    features: features,\n    describe: describe,\n    it_async: it_async,\n    it_sync: it_sync,\n  };\n};\n"
  },
  {
    "path": "lib/plugins/mocha/ScenarioLevelPlugin.js",
    "content": "'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      var itFn = iterator.length === 1 ? base_plugin.it_sync : base_plugin.it_async;\n      itFn(scenario.title, scenario, function (context, scenario, done) {\n        iterator(scenario, done);\n      });\n    });\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n};\n"
  },
  {
    "path": "lib/plugins/mocha/StepLevelPlugin.js",
    "content": "'use strict';\n\nvar $ = require('../../Array');\nvar Platform = require('../../Platform');\nvar BasePlugin = require('./BasePlugin');\n\nmodule.exports.init = function (options) {\n  // eslint-disable-next-line no-redeclare\n  var options = options || {};\n  var platform = new Platform();\n  var container = options.container || platform.get_container();\n\n  var base_plugin = BasePlugin.create(options);\n\n  function scenarios(scenarios, iterator) {\n    $(scenarios).each(function (scenario) {\n      base_plugin.describe(scenario.title, scenario, iterator);\n    });\n  }\n\n  function steps(steps, iterator) {\n    var abort = false;\n\n    $(steps).each(function (step) {\n      var stepFn = iterator.length === 1 ? step_sync : step_async;\n      stepFn(step, iterator);\n    });\n\n    function step_async(step, iterator) {\n      base_plugin.it_async(step, step, function (context, step, done) {\n        if (abort) {\n          return context.skip ? context.skip() : done();\n        }\n        abort = true;\n        iterator.bind(context)(step, function (err) {\n          if (err) return (done.fail || done)(err);\n          abort = false;\n          done();\n        });\n      });\n    }\n\n    function step_sync(step, iterator) {\n      base_plugin.it_sync(step, step, function (context, step) {\n        if (abort) return context.skip && context.skip();\n        abort = true;\n        iterator.bind(context)(step);\n        abort = false;\n      });\n    }\n  }\n\n  container.featureFiles = container.featureFile = base_plugin.featureFiles;\n  container.features = container.feature = base_plugin.features;\n  container.scenarios = container.scenario = scenarios;\n  container.steps = steps;\n};\n"
  },
  {
    "path": "lib/scores/LevenshteinDistanceScore.js",
    "content": "'use strict';\n\n// Understands similarity of two strings\nvar LevenshteinDistanceScore = function (s1, s2) {\n  this.value;\n  this.type = 'LevenshteinDistanceScore';\n  var distance_table;\n  var _this = this;\n\n  var initialise = function () {\n    var x = s1.length;\n    var y = s2.length;\n\n    distance_table = new Array(x + 1);\n\n    /* eslint-disable no-redeclare */\n    for (var i = 0; i <= x; i++) {\n      distance_table[i] = new Array(y + 1);\n    }\n\n    for (var i = 0; i <= x; i++) {\n      for (var j = 0; j <= y; j++) {\n        distance_table[i][j] = 0;\n      }\n    }\n\n    for (var i = 0; i <= x; i++) {\n      distance_table[i][0] = i;\n    }\n\n    for (var j = 0; j <= y; j++) {\n      distance_table[0][j] = j;\n    }\n    /* eslint-enable no-redeclare */\n  };\n\n  var score = function () {\n    // eslint-disable-next-line no-return-assign\n    if (s1 === s2) return (_this.value = 0);\n\n    for (var j = 0; j < s2.length; j++) {\n      for (var i = 0; i < s1.length; i++) {\n        if (s1[i] === s2[j]) {\n          distance_table[i + 1][j + 1] = distance_table[i][j];\n        } else {\n          var deletion = distance_table[i][j + 1] + 1;\n          var insertion = distance_table[i + 1][j] + 1;\n          var substitution = distance_table[i][j] + 1;\n          distance_table[i + 1][j + 1] = Math.min(substitution, deletion, insertion);\n        }\n      }\n    }\n    _this.value = distance_table[s1.length][s2.length];\n  };\n\n  this.compare = function (other) {\n    return other.value - this.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n\n  initialise();\n  score();\n};\n\nmodule.exports = LevenshteinDistanceScore;\n"
  },
  {
    "path": "lib/scores/MultiScore.js",
    "content": "'use strict';\n\nvar $ = require('../Array');\n\nvar MultiScore = function (scores) {\n  this.scores = $(scores);\n  this.type = 'MultiScore';\n\n  this.compare = function (other) {\n    for (var i = 0; i < this.scores.length; i++) {\n      var difference = this.scores[i].compare(other.scores[i]);\n      if (difference) return difference;\n    }\n    return 0;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    if (this.type !== other.type) return false;\n    return this.compare(other) === 0;\n  };\n};\n\nmodule.exports = MultiScore;\n"
  },
  {
    "path": "lib/scores/SameLibraryScore.js",
    "content": "'use strict';\n\nvar SameLibraryScore = function (m1, m2) {\n  this.value = m1.is_sibling(m2) ? 1 : 0;\n  this.type = 'SameLibraryScore';\n\n  this.compare = function (other) {\n    return this.value - other.value;\n  };\n\n  this.equals = function (other) {\n    if (!other) return false;\n    return this.type === other.type && this.value === other.value;\n  };\n};\n\nmodule.exports = SameLibraryScore;\n"
  },
  {
    "path": "lib/shims/index.js",
    "content": "'use strict';\n\nvar Platform = require('../Platform');\n\nmodule.exports = (function () {\n  var platform = new Platform();\n\n  var shims = {\n    node: function () {\n      return {\n        fs: require('fs'),\n        path: require('path'),\n        process: process,\n      };\n    },\n    phantom: function () {\n      return {\n        fs: require('./phantom-fs'),\n        path: require('./phantom-path'),\n        process: require('./phantom-process'),\n      };\n    },\n    karma: function () {\n      return {\n        fs: require('./karma-fs'),\n        path: require('./karma-path'),\n        process: require('./karma-process'),\n      };\n    },\n  };\n\n  function get_shim() {\n    if (platform.is_phantom()) return shims.phantom();\n    if (platform.is_browser() && platform.is_karma()) return shims.karma();\n    if (platform.is_node()) return shims.node();\n    return {};\n  }\n\n  return get_shim();\n})();\n"
  },
  {
    "path": "lib/shims/karma-fs.js",
    "content": "module.exports = (function () {\n  'use strict';\n\n  var path = require('./karma-path');\n\n  function absolutePath(relativePath) {\n    return path.resolve(path.normalize(relativePath.split('\\\\').join('/')));\n  }\n\n  var KarmaFileSystem = function () {\n    this.registry = new KarmaPathRegistry();\n    this.converter = new KarmaUriPathConverter('/base/', '/');\n    this.reader = new KarmaFileReader(this.converter);\n\n    var servedUris = Object.keys(window.__karma__.files);\n    var servedFiles = this.converter.parseUris(servedUris);\n    servedFiles.forEach(this.registry.addFile, this.registry);\n  };\n  KarmaFileSystem.prototype = {\n    constructor: KarmaFileSystem,\n    workingDirectory: '/',\n    existsSync: function (path) {\n      return this.registry.exists(path);\n    },\n    readdirSync: function (path) {\n      return this.registry.getContent(path);\n    },\n    statSync: function (path) {\n      return {\n        isDirectory: function () {\n          return this.registry.isDirectory(path);\n        }.bind(this),\n      };\n    },\n    readFileSync: function (file, encoding) {\n      if (encoding !== 'utf8') throw new Error('This fs.readFileSync() shim does not support other than utf8 encoding.');\n      if (!this.registry.isFile(file)) throw new Error('File does not exist: ' + file);\n      return this.reader.readFile(file);\n    },\n  };\n\n  var KarmaPathRegistry = function KarmaPathRegistry() {\n    this.paths = {};\n  };\n\n  KarmaPathRegistry.prototype = {\n    constructor: KarmaPathRegistry,\n    addFile: function (file) {\n      file = absolutePath(file);\n      this.paths[file] = KarmaPathRegistry.TYPE_FILE;\n      var parentDirectory = path.dirname(file);\n      this.addDirectory(parentDirectory);\n    },\n    addDirectory: function (directory) {\n      directory = absolutePath(directory);\n      this.paths[directory] = KarmaPathRegistry.TYPE_DIRECTORY;\n      var parentDirectory = path.dirname(directory);\n      if (parentDirectory !== directory) this.addDirectory(parentDirectory);\n    },\n    isFile: function (file) {\n      file = absolutePath(file);\n      return this.exists(file) && this.paths[file] === KarmaPathRegistry.TYPE_FILE;\n    },\n    isDirectory: function (directory) {\n      directory = absolutePath(directory);\n      return this.exists(directory) && this.paths[directory] === KarmaPathRegistry.TYPE_DIRECTORY;\n    },\n    exists: function (node) {\n      node = absolutePath(node);\n      return this.paths.hasOwnProperty(node);\n    },\n    getContent: function (directory) {\n      if (!this.isDirectory(directory)) throw new Error('Not a directory: ' + directory);\n      directory = absolutePath(directory);\n      return Object.keys(this.paths)\n        .filter(function (node) {\n          if (node === directory) return false;\n          var parentDirectory = path.dirname(node);\n          return parentDirectory === directory;\n        }, this)\n        .map(function (node) {\n          return path.basename(node);\n        });\n    },\n  };\n\n  KarmaPathRegistry.TYPE_FILE = 0;\n  KarmaPathRegistry.TYPE_DIRECTORY = 1;\n\n  var KarmaUriPathConverter = function KarmaUriPathConverter(baseUri, workingDirectory) {\n    this.workingDirectory = workingDirectory;\n    this.workingDirectoryPattern = this.patternFromBase(workingDirectory);\n    this.baseUri = baseUri;\n    this.baseUriPattern = this.patternFromBase(baseUri);\n  };\n\n  KarmaUriPathConverter.prototype = {\n    constructor: KarmaUriPathConverter,\n    patternFromBase: function (string, flags) {\n      var pattern = '^' + string.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n      return new RegExp(pattern, flags);\n    },\n    parseUris: function (uris) {\n      return uris\n        .filter(function (uri) {\n          return this.baseUriPattern.test(uri);\n        }, this)\n        .map(function (uri) {\n          return uri.replace(this.baseUriPattern, this.workingDirectory);\n        }, this);\n    },\n    buildUri: function (file) {\n      file = absolutePath(file);\n      if (!this.workingDirectoryPattern.test(file)) throw new Error('Path is not in working directory: ' + file);\n      return file.replace(this.workingDirectoryPattern, this.baseUri);\n    },\n  };\n\n  var KarmaFileReader = function KarmaFileReader(converter) {\n    this.converter = converter;\n  };\n\n  KarmaFileReader.prototype = {\n    constructor: KarmaFileReader,\n    readFile: function (file) {\n      var uri = this.converter.buildUri(file);\n      // eslint-disable-next-line no-undef\n      var xhr = new XMLHttpRequest();\n      xhr.open('get', uri, false);\n      xhr.send();\n      return xhr.responseText;\n    },\n  };\n\n  return new KarmaFileSystem();\n})();\n"
  },
  {
    "path": "lib/shims/karma-path.js",
    "content": "module.exports = (function () {\n  'use strict';\n\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    throw new Error(\"The environment does not support the path module, it's probably not using browserify.\");\n  }\n\n  if (typeof path.normalize !== 'function' || typeof path.dirname !== 'function') throw new Error('The path module emulation does not contain implementations of required functions.');\n\n  return path;\n})();\n"
  },
  {
    "path": "lib/shims/karma-process.js",
    "content": "module.exports = (function () {\n  'use strict';\n\n  var fs = require('./karma-fs');\n  var process = {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n"
  },
  {
    "path": "lib/shims/phantom-fs.js",
    "content": "'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n\n  fs.existsSync = fs.existsSync || fs.exists;\n\n  fs.readdirSync =\n    fs.readdirSync ||\n    function (path) {\n      return fs.list(path).filter(function (name) {\n        return name !== '.' && name !== '..';\n      });\n    };\n\n  fs.statSync =\n    fs.statSync ||\n    function (path) {\n      return {\n        isDirectory: function () {\n          return fs.isDirectory(path);\n        },\n      };\n    };\n\n  return fs;\n})();\n"
  },
  {
    "path": "lib/shims/phantom-path.js",
    "content": "'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var path = {};\n\n  try {\n    path = require('path');\n  } catch (e) {\n    // meh\n  }\n\n  path.join =\n    path.join ||\n    function () {\n      return Array.prototype.join.call(arguments, fs.separator);\n    };\n\n  path.relative =\n    path.relative ||\n    function (from, to) {\n      return from + fs.separator + to;\n    };\n\n  return path;\n})();\n"
  },
  {
    "path": "lib/shims/phantom-process.js",
    "content": "'use strict';\n\nmodule.exports = (function () {\n  if (module.client) return {}; // Running in browser, not via node\n\n  var fs = require('fs');\n  var process = typeof process !== 'undefined' ? process : {};\n\n  process.cwd = function () {\n    return fs.workingDirectory;\n  };\n\n  return process;\n})();\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"yadda\",\n  \"version\": \"2.2.0\",\n  \"description\": \"A true BDD framework for JavaScript\",\n  \"main\": \"./lib/index.js\",\n  \"devDependencies\": {\n    \"browserify\": \"^17.0.0\",\n    \"eslint\": \"^8.2.0\",\n    \"eslint-config-prettier\": \"^8.3.0\",\n    \"eslint-plugin-prettier\": \"^4.0.0\",\n    \"husky\": \"^7.0.4\",\n    \"karma\": \"^6.3.7\",\n    \"karma-browserify\": \"^8.1.0\",\n    \"karma-mocha\": \"^2.0.1\",\n    \"karma-phantomjs-launcher\": \"^1.0.4\",\n    \"lint-staged\": \"^11.2.6\",\n    \"mocha\": \"^9.1.3\",\n    \"nyc\": \"^15.1.0\",\n    \"phantomjs-prebuilt\": \"^2.1.16\",\n    \"prettier\": \"2.4.1\",\n    \"watchify\": \"^4.0.0\"\n  },\n  \"directories\": {\n    \"example\": \"examples\",\n    \"test\": \"test\"\n  },\n  \"lint-staged\": {\n    \"**/*\": \"prettier --write --ignore-unknown\"\n  },\n  \"scripts\": {\n    \"test\": \"mocha\",\n    \"karma\": \"karma start karma.conf.js\",\n    \"nyc\": \"nyc --exclude 'test/**' --exclude 'lib/plugins/**' --exclude 'lib/shims/**' --exclude 'lib/Platform.js' --reporter text-summary --reporter=lcov mocha\",\n    \"examples\": \"node bin/examples.js\",\n    \"browserify\": \"node bin/browserify.js\",\n    \"lint\": \"eslint .\",\n    \"lint-staged\": \"lint-staged\",\n    \"coverage\": \"nyc --report html --reporter lcov --reporter text-summary npm test\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/acuminous/yadda.git\"\n  },\n  \"keywords\": [\n    \"BDD\",\n    \"Specification\",\n    \"Natural\",\n    \"Test\",\n    \"Behaviour\",\n    \"Driven\",\n    \"Jasmine\",\n    \"Mocha\",\n    \"QUnit\",\n    \"Nodeunit\"\n  ],\n  \"author\": \"Stephen Cresswell\",\n  \"license\": \"Apache-2.0\",\n  \"bugs\": {\n    \"url\": \"https://github.com/acuminous/yadda/issues\"\n  },\n  \"homepage\": \"http://acuminous.gitbooks.io/yadda-user-guide\",\n  \"dependencies\": {},\n  \"husky\": {\n    \"hooks\": {\n      \"pre-push\": \"npm run lint && npm test && npm run codeclimate\"\n    }\n  }\n}\n"
  },
  {
    "path": "test/ArrayTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar $ = require('../lib/Array');\n\ndescribe('Array', function () {\n  it('should flatten a nested array', function () {\n    assert.deepEqual($([1, 2, 3]).flatten().naked(), [1, 2, 3]);\n    assert.deepEqual(\n      $([1, [2], 3])\n        .flatten()\n        .naked(),\n      [1, 2, 3]\n    );\n    assert.deepEqual(\n      $([1, [[2], 3]])\n        .flatten()\n        .naked(),\n      [1, 2, 3]\n    );\n    assert.deepEqual(\n      $([1, [[2], 3]], [])\n        .flatten()\n        .naked(),\n      [1, 2, 3]\n    );\n  });\n\n  it('should flatten an empty array', function () {\n    assert.deepEqual($([]).flatten().naked(), []);\n  });\n\n  it('should iterate asynchronously', function () {\n    var items = [1, 2, 3];\n    var iterations = 0;\n    $(items).each_async(\n      function (item, index, callback) {\n        assert.equal(item, items[iterations]);\n        assert.equal(index, iterations);\n        iterations++;\n        callback(null, item);\n      },\n      function (err, result) {\n        assert.ifError(err);\n        assert.equal(result, 3);\n      }\n    );\n  });\n\n  it('should return the last item', function () {\n    assert.equal($([1, 2, 3]).last(), 3);\n  });\n\n  it('should fill an array with n items', function () {\n    assert.deepEqual($([]).fill('A', 3).naked(), ['A', 'A', 'A']);\n  });\n});\n"
  },
  {
    "path": "test/CompetitionTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Macro = require('../lib/Macro');\nvar Competition = require('../lib/Competition');\nvar Dictionary = require('../lib/Dictionary');\nvar fn = require('../lib/fn');\n\ndescribe('Competition', function () {\n  it('should decide winner by Levenshtein distance', function () {\n    var best_match = new Macro('best', parsed_signature(/given 1 (.*) patient/));\n    var middle_match = new Macro('middle', parsed_signature(/given (\\d+) (.*) patient(?:s{0,1})/));\n    var worst_match = new Macro('worse', parsed_signature(/given (\\d+) (.*) (?:patient|patients)/));\n    var competition = new Competition('given 1 male patient', [worst_match, best_match, middle_match]);\n\n    assert.equal(competition.clear_winner().signature, best_match.signature);\n  });\n\n  it('should decide winner by Levenshtein distance on multiline', function () {\n    var best_match = new Macro('best', parsed_signature(/given 1 ([^\\u0000]*) text/));\n    var middle_match = new Macro('middle', parsed_signature(/given (\\d+) ([^\\u0000]*) text (?:s{0,1})/));\n    var worst_match = new Macro('worse', parsed_signature(/given (\\d+) ([^\\u0000]*) (?:text|code)/));\n    var competition = new Competition('given 1 a\\nb\\nc text', [worst_match, best_match, middle_match]);\n\n    assert.equal(competition.clear_winner().signature, best_match.signature);\n  });\n\n  it('should decide tie breakers by prefering to macro from the same library as the previous winner', function () {\n    var library1 = { name: 'l1' };\n    var library2 = { name: 'l2' };\n    var previous_match = new Macro('previous', parsed_signature(/whatever/), fn.noop, {}, library1);\n    var best_match = new Macro('best', parsed_signature(/given 1 (.*) patient/), fn.noop, {}, library1);\n    var equal_match = new Macro('equal', parsed_signature(/given 1 (.+) patient/), fn.noop, {}, library2);\n    var competition = new Competition('given 1 male patient', [best_match, equal_match], previous_match);\n\n    assert.equal(competition.clear_winner().signature, best_match.signature);\n  });\n\n  it('should support joint winners', function () {\n    var library1 = { name: 'l1' };\n    var previous_match = new Macro('previous', parsed_signature(/whatever/), fn.noop, {}, library1);\n    var best_match = new Macro('best', parsed_signature(/given 1 (.*) patient/), fn.noop, {}, library1);\n    var equal_match = new Macro('equal', parsed_signature(/given 1 (.+) patient/), fn.noop, {}, library1);\n    var competition = new Competition('given 1 male patient', [best_match, equal_match], previous_match);\n\n    assert.throws(function () {\n      competition.clear_winner();\n    }, /Ambiguous Step: \\[given 1 male patient\\]. Patterns \\[\\/best\\/, \\/equal\\/\\] match equally well./);\n  });\n\n  it('should support multiline joint winners', function () {\n    var best_match = new Macro('best', /given ([^\\u0000]*) text/);\n    var equal_match = new Macro('equal', /given ([^\\u0000]+) text/);\n    var competition = new Competition('given 1\\n2\\n3 text', [best_match, equal_match]);\n\n    assert.throws(function () {\n      competition.clear_winner();\n    }, /Ambiguous Step: \\[given 1\\n2\\n3 text\\]. Patterns \\[\\/best\\/, \\/equal\\/\\] match equally well./);\n  });\n\n  it('Should support no winner', function () {\n    var competition = new Competition('given 1 male patient', []);\n\n    assert.throws(function () {\n      competition.clear_winner();\n    }, /Undefined Step: \\[given 1 male patient\\]/);\n  });\n\n  function parsed_signature(pattern) {\n    return new Dictionary().define('foo', pattern).expand('$foo');\n  }\n});\n"
  },
  {
    "path": "test/ContextTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Context = require('../lib/Context');\n\ndescribe('Context', function () {\n  it('should merge objects', function () {\n    assert_merge_context({ a: 1 }, undefined, { a: 1 });\n    assert_merge_context({ a: 1 }, null, { a: 1 });\n    assert_merge_context({ a: 1 }, {}, { a: 1 });\n    assert_merge_context({ a: 1 }, { b: 2 }, { a: 1, b: 2 });\n    assert_merge_context({ a: 1 }, { a: 2 }, { a: 2 });\n\n    assert_merge_context(undefined, { a: 1 }, { a: 1 });\n    assert_merge_context(null, { a: 1 }, { a: 1 });\n    assert_merge_context({}, { a: 1 }, { a: 1 });\n    assert_merge_context({ b: 2 }, { a: 1 }, { a: 1, b: 2 });\n    assert_merge_context({ a: 2 }, { a: 1 }, { a: 1 });\n  });\n\n  it('should merge contexts', function () {\n    assert.deepEqual(new Context({ a: 1 }).merge(new Context({ b: 2 })).properties, new Context({ a: 1, b: 2 }).properties);\n  });\n\n  var assert_merge_context = function (thing1, thing2, expected) {\n    assert.deepEqual(new Context(thing1).merge(thing2).properties, expected);\n  };\n});\n"
  },
  {
    "path": "test/Counter.js",
    "content": "'use strict';\n\nmodule.exports = function () {\n  var tally = 0;\n\n  this.count = function (next) {\n    tally++;\n    next && next();\n  };\n\n  this.total = function () {\n    return tally;\n  };\n};\n"
  },
  {
    "path": "test/DictionaryTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Dictionary = require('../lib/index').Dictionary;\nvar pass_through_converter = require('../lib/converters/pass-through-converter');\n\ndescribe('Dictionary', function () {\n  it('should default to a wild card match', function () {\n    assert_pattern(new Dictionary(), '$missing', '(.+)');\n  });\n\n  it('should expand simple terms', function () {\n    var dictionary = new Dictionary().define('gender', '(male|female)').define('speciality', /(cardiovascular|elderly care)/);\n\n    assert_pattern(dictionary, '$gender', '(male|female)');\n    assert_pattern(dictionary, '$speciality', '(cardiovascular|elderly care)');\n    assert_pattern(dictionary, 'Given a $gender, $speciality patient called $name', 'Given a (male|female), (cardiovascular|elderly care) patient called (.+)');\n  });\n\n  it('should expand complex terms', function () {\n    var dictionary = new Dictionary().define('address_line_1', '$number $street').define('number', /(\\d+)/).define('street', /(\\w+)/);\n\n    assert_pattern(dictionary, '$address_line_1', '(\\\\d+) (\\\\w+)');\n  });\n\n  it('should report duplicate terms', function () {\n    var dictionary = new Dictionary().define('gender', '(male|female)');\n\n    assert.throws(function () {\n      dictionary.define('gender', 'anything');\n    }, /Duplicate term: \\[gender\\]/);\n  });\n\n  it('should report cyclic definitions', function () {\n    var dictionary = new Dictionary().define('direct', '$direct').define('indirect', '$intermediary').define('intermediary', '$indirect');\n\n    assert.throws(function () {\n      dictionary.expand('$direct');\n    }, /Circular Definition: \\[direct\\]/);\n\n    assert.throws(function () {\n      dictionary.expand('$indirect');\n    }, /Circular Definition: \\[indirect, intermediary\\]/);\n  });\n\n  it('should merge with another dictionary', function () {\n    var dictionary1 = new Dictionary().define('gender', /(male|female)/);\n    var dictionary2 = new Dictionary().define('speciality', /(cardiovascular|elderly care)/);\n    var dictionary3 = dictionary1.merge(dictionary2);\n\n    assert_pattern(dictionary3, '$gender', '(male|female)');\n    assert_pattern(dictionary3, '$speciality', '(cardiovascular|elderly care)');\n  });\n\n  it('should maintain prefix when merging dictionaries', function () {\n    var dictionary1 = new Dictionary(':').define('gender', /(male|female)/);\n    var dictionary2 = new Dictionary(':').merge(dictionary1);\n    assert_pattern(dictionary2, ':gender', '(male|female)');\n  });\n\n  it('should not merge dictionaries with different prefixes', function () {\n    var dictionary1 = new Dictionary('$');\n    var dictionary2 = new Dictionary(':');\n\n    assert.throws(function () {\n      dictionary1.merge(dictionary2);\n    }, /Cannot merge dictionaries with different prefixes/);\n  });\n\n  it('should report duplicate terms in merged dictionaries', function () {\n    var dictionary1 = new Dictionary().define('gender', /(male|female)/);\n    var dictionary2 = new Dictionary().define('gender', /(male|female)/);\n\n    assert.throws(function () {\n      dictionary1.merge(dictionary2);\n    }, /Duplicate term: \\[gender\\]/);\n  });\n\n  it('should return a pass through converter each matching group', function () {\n    var dictionary = new Dictionary();\n    assert_converters(dictionary, /(1) (2) (3)/, [pass_through_converter, pass_through_converter, pass_through_converter]);\n  });\n\n  it('should return a pass through converter each undefined term', function () {\n    var dictionary = new Dictionary();\n    assert_converters(dictionary, '$foo $bar', [pass_through_converter, pass_through_converter]);\n  });\n\n  it('should default to the pass through converter for each matching group in a defined pattern', function () {\n    var dictionary = new Dictionary().define('foo', /(1)/).define('bar', /(2) (3)/);\n    assert_converters(dictionary, '$foo $bar', [pass_through_converter, pass_through_converter, pass_through_converter]);\n  });\n\n  it('should use the specified converters when specified', function () {\n    var converter1 = function a(value, cb) {};\n    var converter2 = function b(value, cb) {};\n    var dictionary = new Dictionary().define('foo', /(1)/, converter1).define('bar', /(2) (3)/, [converter1, converter2]);\n    assert_converters(dictionary, '$foo $bar', [converter1, converter1, converter2]);\n  });\n\n  it('should allow patterns and terms to be mixed in the same signature', function () {\n    var converter1 = function a(value, cb) {};\n    var converter2 = function b(value, cb) {};\n    var dictionary = new Dictionary().define('foo', /(1)/, converter1).define('bar', /(2) (3)/, [converter1, converter2]);\n    assert_converters(dictionary, '(1) $foo (2) (3) $bar (4) $baz', [pass_through_converter, converter1, pass_through_converter, pass_through_converter, converter1, converter2, pass_through_converter, pass_through_converter]);\n  });\n\n  it('should report expandable terms with converters', function () {\n    assert.throws(function () {\n      new Dictionary().define('address_line_1', '$number $street', pass_through_converter);\n    }, /Expandable terms cannot use converters: \\[address_line_1\\]/);\n  });\n\n  it('should report terms with wrong number of converters for matching groups', function () {\n    assert.throws(function () {\n      new Dictionary().define('foo', '(1)', [pass_through_converter, pass_through_converter]);\n    }, /Wrong number of converters for: \\[foo\\]/);\n  });\n\n  it('should support multi-arg converters', function () {\n    var two_arg_converter = function (a, b, cb) {};\n\n    var dictionary = new Dictionary().define('foo', '(1) (2)', [two_arg_converter]);\n    assert_converters(dictionary, '$foo', [two_arg_converter]);\n  });\n\n  it('should report multi-arg converters with the wrong number of matching groups', function () {\n    var two_arg_converter = function (a, b, cb) {};\n\n    assert.throws(function () {\n      new Dictionary().define('foo', '(1)', [two_arg_converter]);\n    }, /Wrong number of converters for: \\[foo\\]/);\n  });\n\n  function assert_pattern(dictionary, pattern, expected) {\n    assert.equal(dictionary.expand(pattern).pattern, expected);\n  }\n\n  function assert_converters(dictionary, pattern, expected) {\n    var converters = dictionary.expand(pattern).converters;\n    assert.equal(converters.length, expected.length);\n    for (var i = 0; i < expected.length; i++) {\n      assert.equal(converters[i].toString(), expected[i].toString());\n    }\n  }\n});\n"
  },
  {
    "path": "test/EventBusTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar EventBus = require('../lib/EventBus');\n\ndescribe('EventBus', function () {\n  var bus = EventBus.instance();\n\n  it('should carry an event to a listener', function () {\n    var listener = new Listener();\n    bus.on('foo', listener.listen).send('foo');\n\n    assert.equal(1, listener.events.length);\n    assert_event('foo', {}, listener.events[0]);\n  });\n\n  it('should allow events to include data', function () {\n    var listener = new Listener();\n    bus.on('foo', listener.listen).send('foo', { foo: 'bar' });\n\n    assert.equal(1, listener.events.length);\n    assert_event('foo', { foo: 'bar' }, listener.events[0]);\n  });\n\n  it('should carry an event to multiple listeners', function () {\n    var listener1 = new Listener();\n    var listener2 = new Listener();\n    bus.on('foo', listener1.listen).on('foo', listener2.listen).send('foo');\n\n    assert.equal(1, listener1.events.length);\n    assert.equal(1, listener2.events.length);\n  });\n\n  it('should send all matching events to a listener', function () {\n    var listener = new Listener();\n    bus.on(/f.*/, listener.listen).send('foo');\n    assert.equal(1, listener.events.length);\n  });\n\n  it('should not send unmatched events to a listener', function () {\n    var listener = new Listener();\n    bus.on(/f.*/, listener.listen).send('bar');\n    assert.equal(0, listener.events.length);\n  });\n\n  it('should execute callbacks without event data', function (done) {\n    var listener = new Listener();\n    bus.on(/f.*/, listener.listen).send('bar', done);\n  });\n\n  it('should execute callbacks with event data', function (done) {\n    var listener = new Listener();\n    bus.on(/f.*/, listener.listen).send('bar', {}, done);\n  });\n\n  function Listener() {\n    var _this = this;\n    this.events = [];\n    this.listen = function (event) {\n      _this.events.push(event);\n    };\n  }\n\n  function assert_event(name, data, event) {\n    assert.ok(event);\n    assert.equal(name, event.name);\n    assert.deepEqual(data, event.data);\n  }\n});\n"
  },
  {
    "path": "test/FeatureFileSearchTests.js",
    "content": "'use strict';\n\nvar path = require('../lib/shims').path;\nvar assert = require('assert');\nvar FeatureFileSearch = require('../lib/FeatureFileSearch');\n\ndescribe('FeatureFileSearch', function () {\n  it('should return only feature files', function () {\n    var files = new FeatureFileSearch('./test/filesearch').list();\n    assert.equal(files.length, 3);\n    assert.equal(files[0], path.join('test', 'filesearch', 'include.feature'));\n    assert.equal(files[1], path.join('test', 'filesearch', 'subdir1', 'include.spec'));\n    assert.equal(files[2], path.join('test', 'filesearch', 'subdir2', 'subdir3', 'include.specification'));\n  });\n});\n"
  },
  {
    "path": "test/FeatureParserTests.js",
    "content": "'use strict';\n\nvar fs = require('../lib/shims').fs;\nvar path = require('../lib/shims').path;\nvar assert = require('assert');\nvar FeatureParser = require('../lib/index').parsers.FeatureParser;\nvar Localisation = require('../lib/index').localisation;\nvar Language = require('../lib/index').localisation.Language;\nvar Pirate = require('../lib/index').localisation.Pirate;\nvar English = require('../lib/index').localisation.English;\n\ndescribe('FeatureParser', function () {\n  afterEach(function () {\n    Localisation.default = English;\n  });\n\n  describe('(Features)', function () {\n    it('should parse feature title', function () {\n      var feature = parse_file('feature/simple_feature');\n      assert.equal(feature.title, 'Simple Feature');\n    });\n\n    it('should parse feature descriptions', function () {\n      var feature = parse_file('feature/feature_description');\n      assert.equal(feature.title, 'Feature Description');\n      assert.equal(feature.description.join(' - '), 'As a wood chopper - I want to maintain a sharp axe - So that I can chop wood');\n    });\n\n    it('should only allow a single feature', function () {\n      assert.throws(function () {\n        parse_file('feature/multiple_features');\n      }, /Feature is unexpected/);\n    });\n\n    it('should report incomplete features', function () {\n      assert.throws(function () {\n        parse_file('feature/incomplete_feature');\n      }, /Feature requires one or more scenarios/);\n    });\n  });\n\n  describe('(Scenarios)', function () {\n    it('should parse a simple scenario', function () {\n      var scenarios = parse_file('scenario/simple_scenario').scenarios;\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Simple Scenario');\n      assert.deepEqual(scenarios[0].steps, ['Given A', 'When B', 'Then C']);\n    });\n\n    it('should parse a complex scenario', function () {\n      var scenarios = parse_file('scenario/complex_scenario').scenarios;\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Complex Scenario');\n      assert.deepEqual(scenarios[0].steps, ['Given A', 'When B', 'Then C']);\n    });\n\n    it('should parse multiple scenarios', function () {\n      var scenarios = parse_file('scenario/multiple_scenarios').scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[1].title, 'Second Scenario');\n    });\n\n    it('should reset scenarios between parses', function () {\n      assert.equal(parse_file('scenario/simple_scenario').scenarios.length, 1);\n      assert.equal(parse_file('scenario/simple_scenario').scenarios.length, 1);\n    });\n\n    it('should report incomplete scenarios', function () {\n      assert.throws(function () {\n        parse_file('scenario/incomplete_scenario_1');\n      }, /Scenario requires one or more steps/);\n\n      assert.throws(function () {\n        parse_file('scenario/incomplete_scenario_2');\n      }, /Scenario requires one or more steps/);\n\n      assert.throws(function () {\n        parse_file('scenario/incomplete_scenario_3');\n      }, /Scenario requires one or more steps/);\n\n      assert.throws(function () {\n        parse_file('scenario/incomplete_scenario_4');\n      }, /Scenario requires one or more steps/);\n    });\n\n    it('should report steps with no scenario', function () {\n      assert.throws(function () {\n        parse_file('scenario/missing_scenario');\n      }, /A feature must contain one or more scenarios/);\n    });\n\n    it('should parse multline steps with no ending dash', function () {\n      var scenarios = parse_file('scenario/multiline_step_scenario').scenarios;\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Multiline Step');\n      assert.equal(scenarios[0].steps[0], poem);\n    });\n\n    it('should parse multiline steps', function () {\n      var scenarios = parse_file('scenario/multiline_step_scenario_with_ending_dash').scenarios;\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Multiline Step With Ending Dash');\n      assert.equal(scenarios[0].steps[0], poem);\n    });\n\n    it('should parse multiline steps with followers', function () {\n      var scenarios = parse_file('scenario/multiline_step_scenario_with_followers').scenarios;\n      assert.equal(scenarios.length, 5);\n      assert.equal(scenarios[0].title, 'Multiline Step Followed By Scenario');\n      assert.equal(scenarios[0].steps[0], poem);\n\n      assert.equal(scenarios[1].title, 'Another scenario');\n\n      assert.equal(scenarios[2].title, 'Multiline Step Followed By Annotation');\n      assert.equal(scenarios[2].steps[0], poem);\n\n      assert.equal(scenarios[3].title, 'Another scenario');\n\n      assert.equal(scenarios[4].title, 'Multiline Step Followed By Example Table');\n      assert.equal(JSON.stringify(scenarios[4].steps[0]), JSON.stringify(poem));\n    });\n\n    it('should parse multiple multiline steps in the same scenario', function () {\n      var scenarios = parse_file('scenario/multiline_step_scenario_with_multiple_blocks').scenarios;\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Multiline Step With Multiple Blocks');\n      assert.equal(scenarios[0].steps[0], ['Verse 1'].concat(poem.split('\\n').splice(1, 4)).join('\\n'));\n      assert.equal(scenarios[0].steps[1], ['Verse 2'].concat(poem.split('\\n').splice(6, 9)).join('\\n'));\n    });\n\n    it('should append the final blank line in a multiple step', function () {\n      var scenarios = parse_file('scenario/multiline_step_scenario_with_multiple_blocks_and_blank').scenarios;\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Multiline Step With Multiple Blocks And Blank');\n      assert.equal(scenarios[0].steps[0], ['Verse 1'].concat(poem.split('\\n').splice(1, 4)).concat('').join('\\n'));\n      assert.equal(scenarios[0].steps[1], ['Verse 2'].concat(poem.split('\\n').splice(6, 9)).concat('').join('\\n'));\n    });\n\n    it('should maintain indentation while parsing multiline steps', function () {\n      var scenarios = parse_file('scenario/multiline_step_scenario_with_indentation').scenarios;\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Multiline Step With Indentation');\n      assert.equal(scenarios[0].steps[0], ['LOLCODE', 'HAI', 'CAN HAS STDIO?', 'PLZ OPEN FILE \"LOLCATS.TXT\"?', '    AWSUM THX', '        VISIBLE FILE', '    O NOES', '        INVISIBLE \"ERROR!\"', 'KTHXBYE'].join('\\n'));\n    });\n\n    it('should report malformed multiline steps', function () {\n      assert.throws(function () {\n        parse_file('scenario/malformed_multiline_scenario_1');\n      }, /Dash is unexpected at this time/);\n\n      assert.throws(function () {\n        parse_file('scenario/malformed_multiline_scenario_2');\n      }, /Indentation error/);\n\n      assert.throws(function () {\n        parse_file('scenario/malformed_multiline_scenario_3');\n      }, /Dash is unexpected at this time/);\n\n      assert.throws(function () {\n        parse_file('scenario/malformed_multiline_scenario_4');\n      }, /Examples is unexpected at this time/);\n\n      assert.throws(function () {\n        parse_file('scenario/malformed_multiline_scenario_5');\n      }, /Annotation is unexpected at this time/);\n    });\n  });\n\n  describe('(Annotations)', function () {\n    it('should parse feature annotations', function () {\n      var feature = parse_file('annotated/annotated_feature');\n      assert.equal(feature.annotations.keyword1, 'value1');\n      assert.equal(feature.annotations.keyword2, 'value2');\n      assert(feature.annotations.keyword3);\n      assert.equal(Object.keys(feature.scenarios[0].annotations).length, 0);\n    });\n\n    it('should trim feature annotations', function () {\n      var feature = parse_file('annotated/untrimmed_annotated_feature');\n      assert.equal(feature.annotations.keyword1, 'value1');\n      assert.equal(feature.annotations.keyword2, 'value2');\n      assert(feature.annotations.keyword3);\n      assert.equal(Object.keys(feature.scenarios[0].annotations).length, 0);\n    });\n\n    it('should parse scenario annotations', function () {\n      var feature = parse_file('annotated/annotated_scenario');\n      assert.equal(Object.keys(feature.annotations).length, 0);\n      assert.equal(feature.scenarios[0].annotations.keyword1, 'value1');\n      assert.equal(feature.scenarios[0].annotations.keyword2, 'value2');\n      assert(feature.scenarios[0].annotations.keyword3);\n    });\n\n    it('should trim scenario annotations', function () {\n      var feature = parse_file('annotated/untrimmed_annotated_scenario');\n      assert.equal(Object.keys(feature.annotations).length, 0);\n      assert.equal(feature.scenarios[0].annotations.keyword1, 'value1');\n      assert.equal(feature.scenarios[0].annotations.keyword2, 'value2');\n      assert(feature.scenarios[0].annotations.keyword3);\n    });\n\n    it('should support annotations with non alphanumerics', function () {\n      var feature = parse_file('annotated/annotated_feature_non_alphanumeric');\n      assert.equal(feature.annotations['keyword+1'], 'value1');\n      assert.equal(feature.scenarios[0].annotations['keyword-1'], 'value1');\n    });\n\n    it('should expand scenarios from annotated singleline example table', function () {\n      var scenarios = parse_file('annotated/annotated_example_table').scenarios;\n      assert.equal(scenarios.length, 4);\n      assert.equal(scenarios[0].annotations.pending, true);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[0].steps[0], 'Step A11');\n      assert.equal(scenarios[0].steps[1], 'Step 1AA');\n      assert.equal(scenarios[1].annotations.pending, undefined);\n      assert.equal(scenarios[1].title, 'Second Scenario');\n      assert.equal(scenarios[1].steps[0], 'Step B22');\n      assert.equal(scenarios[1].steps[1], 'Step 2BB');\n      assert.equal(scenarios[2].annotations.pending, true);\n      assert.equal(scenarios[2].title, 'Third Scenario');\n      assert.equal(scenarios[2].steps[0], 'Step C33');\n      assert.equal(scenarios[2].steps[1], 'Step 3CC');\n    });\n\n    it('should expand scenarios from annotated multiline example table', function () {\n      var scenarios = parse_file('annotated/annotated_multiline_example_table').scenarios;\n      assert.equal(scenarios.length, 4);\n      assert.equal(scenarios[0].annotations.pending, true);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[0].steps[0], 'Step A11');\n      assert.equal(scenarios[0].steps[1], 'Step 1AA');\n      assert.equal(scenarios[1].annotations.pending, undefined);\n      assert.equal(scenarios[1].title, 'Second Scenario');\n      assert.equal(scenarios[1].steps[0], 'Step B22');\n      assert.equal(scenarios[1].steps[1], 'Step 2BB');\n      assert.equal(scenarios[2].annotations.pending, true);\n      assert.equal(scenarios[2].title, 'Third Scenario');\n      assert.equal(scenarios[2].steps[0], 'Step C33');\n      assert.equal(scenarios[2].steps[1], 'Step 3CC');\n    });\n\n    it('should merge scenario annotations with example table annotations', function () {\n      var scenarios = parse_file('annotated/annotated_example_table').scenarios;\n      assert.equal(scenarios.length, 4);\n      assert.equal(scenarios[0].annotations.pending, true);\n      assert.equal(scenarios[0].annotations.only, true);\n      assert.equal(scenarios[1].annotations.pending, undefined);\n      assert.equal(scenarios[1].annotations.only, true);\n      assert.equal(scenarios[2].annotations.pending, true);\n      assert.equal(scenarios[2].annotations.only, true);\n\n      delete scenarios[0].annotations.pending;\n      assert.equal(scenarios[2].annotations.pending, true);\n    });\n\n    it('should not confuse example table annotations and scenario annotations', function () {\n      var scenarios = parse_file('annotated/annotated_example_table').scenarios;\n      assert.equal(scenarios.length, 4);\n      assert.equal(scenarios[3].annotations.crystal, true);\n    });\n\n    it('should parse scenario annotations after background', function () {\n      var feature = parse_file('annotated/annotated_scenario_after_background');\n      assert.equal(feature.scenarios[0].steps[0], 'Given A');\n    });\n  });\n\n  describe('(Single line Example Tables)', function () {\n    it('should expand scenarios from example table', function () {\n      var scenarios = parse_file('example_table/example_table').scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[0].steps[0], 'Step A11');\n      assert.equal(scenarios[0].steps[1], 'Step 1AA');\n      assert.equal(scenarios[1].title, 'Second Scenario');\n      assert.equal(scenarios[1].steps[0], 'Step B22');\n      assert.equal(scenarios[1].steps[1], 'Step 2BB');\n    });\n\n    it('should expand scenarios from example table with chevrons', function () {\n      var scenarios = parse_file('example_table/example_table_with_chevrons', {\n        leftPlaceholderChar: '<',\n        rightPlaceholderChar: '>',\n      }).scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[0].steps[0], 'Step A11');\n      assert.equal(scenarios[0].steps[1], 'Step 1AA');\n      assert.equal(scenarios[1].title, 'Second Scenario');\n      assert.equal(scenarios[1].steps[0], 'Step B22');\n      assert.equal(scenarios[1].steps[1], 'Step 2BB');\n    });\n\n    it('should expand scenarios from example table using \\\\u2506 separator', function () {\n      var scenarios = parse_file('example_table/example_table_2506').scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[0].steps[0], 'Step A11');\n      assert.equal(scenarios[0].steps[1], 'Step 1AA');\n      assert.equal(scenarios[1].title, 'Second Scenario');\n      assert.equal(scenarios[1].steps[0], 'Step B22');\n      assert.equal(scenarios[1].steps[1], 'Step 2BB');\n    });\n\n    it('should expand scenarios from example table with outer borders', function () {\n      var scenarios = parse_file('example_table/example_table_with_outer_borders').scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[0].steps[0], 'Step A11');\n      assert.equal(scenarios[0].steps[1], 'Step 1AA');\n      assert.equal(scenarios[1].title, 'Second Scenario');\n      assert.equal(scenarios[1].steps[0], 'Step B22');\n      assert.equal(scenarios[1].steps[1], 'Step 2BB');\n    });\n\n    it('should stash annotations for following scenarios', function () {\n      var scenarios = parse_file('example_table/example_table_followed_by_annotated_scenario').scenarios;\n      assert.equal(scenarios.length, 3);\n      assert.equal(scenarios[2].title, 'Annotated Scenario');\n      assert(scenarios[2].annotations.pending);\n    });\n\n    it('should report malformed singleline example tables', function () {\n      assert.throws(function () {\n        parse_file('example_table/malformed_example_table_1').scenarios;\n      }, /Incorrect number of fields in example table/);\n\n      assert.throws(function () {\n        parse_file('example_table/malformed_example_table_2').scenarios;\n      }, /Blank is unexpected at this time/);\n\n      assert.throws(function () {\n        parse_file('example_table/malformed_example_table_3').scenarios;\n      }, /Text is unexpected at this time/);\n    });\n\n    it('should report incomplete example table', function () {\n      assert.throws(function () {\n        parse_file('example_table/incomplete_example_table_1');\n      }, /Examples table requires one or more headings/);\n\n      assert.throws(function () {\n        parse_file('example_table/incomplete_example_table_2');\n      }, /Examples table requires one or more rows/);\n\n      assert.throws(function () {\n        parse_file('example_table/incomplete_example_table_3');\n      }, /Scenario is unexpected at this time/);\n\n      assert.throws(function () {\n        parse_file('example_table/incomplete_example_table_4');\n      }, /Scenario is unexpected at this time/);\n    });\n\n    it('should expand feature background from example table', function () {\n      var feature = parse_file('example_table/feature_with_background_and_example_table');\n      assert.equal(feature.scenarios.length, 4);\n      assert.equal(feature.scenarios[0].steps[0], 'BG A1');\n      assert.equal(feature.scenarios[1].steps[0], 'BG B2');\n      assert.equal(feature.scenarios[2].steps[0], 'BG X3');\n      assert.equal(feature.scenarios[3].steps[0], 'BG Y4');\n    });\n\n    it('should add meta fields to example table', function () {\n      var scenarios = parse_file('example_table/meta_fields').scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[0].steps[0], '1 First 9:5');\n      assert.equal(scenarios[0].steps[1], '1 A 9:14');\n      assert.equal(scenarios[0].steps[2], '1 1 9:23');\n      assert.equal(scenarios[1].title, 'Second Scenario');\n      assert.equal(scenarios[1].steps[0], '2 Second 10:5');\n      assert.equal(scenarios[1].steps[1], '2 B 10:14');\n      assert.equal(scenarios[1].steps[2], '2 2 10:23');\n    });\n\n    it('should expand multiline step scenarios from example table', function () {\n      var scenarios = parse_file('example_table/multiline_step_example_table').scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'First Scenario');\n      assert.equal(scenarios[0].steps[0], 'Step\\nA11\\n1AA');\n      assert.equal(scenarios[1].title, 'Second Scenario');\n      assert.equal(scenarios[1].steps[0], 'Step\\nB22\\n2BB');\n    });\n  });\n\n  describe('(Multiline Example Tables)', function () {\n    it('should expand scenarios from simple multiline example table', function () {\n      var scenarios = parse_file('example_table/simple_multiline_example_table').scenarios;\n      assert.equal(scenarios.length, 2);\n\n      assert.equal(scenarios[0].title, 'Simple Multiline Example Table');\n      assert.equal(scenarios[0].steps.length, 2);\n      assert.equal(scenarios[0].steps[0], 'Step left 1');\n      assert.equal(scenarios[0].steps[1], ['Step right 1', 'right 2'].join('\\n'));\n\n      assert.equal(scenarios[1].title, 'Simple Multiline Example Table');\n      assert.equal(scenarios[1].steps.length, 2);\n      assert.equal(scenarios[1].steps[0], ['Step left 3', 'left 4'].join('\\n'));\n      assert.equal(scenarios[1].steps[1], 'Step right 3');\n    });\n\n    it('should expand scenarios from complex multiline examples', function () {\n      var scenarios = parse_file('example_table/complex_multiline_example_table').scenarios;\n      assert.equal(scenarios.length, 2);\n\n      assert.equal(scenarios[0].title, 'Complex Multiline Example Table');\n      assert.equal(scenarios[0].steps.length, 2);\n      assert.equal(scenarios[0].steps[0], 'Step x {\\n  y\\n }');\n      assert.equal(scenarios[0].steps[1], 'Step foo');\n\n      assert.equal(scenarios[1].title, 'Complex Multiline Example Table');\n      assert.equal(scenarios[0].steps.length, 2);\n      assert.equal(scenarios[1].steps[0], 'Step ');\n      assert.equal(scenarios[1].steps[1], 'Step x {\\n  y\\n }');\n    });\n\n    it('should expand scenarios from multiline example table with outer border', function () {\n      var scenarios = parse_file('example_table/multiline_example_table_with_outer_border').scenarios;\n      assert.equal(scenarios.length, 2);\n\n      assert.equal(scenarios[0].title, 'Multiline Example Table With Outer Border');\n      assert.equal(scenarios[0].steps.length, 2);\n      assert.equal(scenarios[0].steps[0], 'Step left 1');\n      assert.equal(scenarios[0].steps[1], ['Step right 1', 'right 2'].join('\\n'));\n\n      assert.equal(scenarios[1].title, 'Multiline Example Table With Outer Border');\n      assert.equal(scenarios[1].steps.length, 2);\n      assert.equal(scenarios[1].steps[0], ['Step left 3', 'left 4'].join('\\n'));\n      assert.equal(scenarios[1].steps[1], 'Step right 3');\n    });\n\n    it('should report malformed multiline examples', function () {\n      assert.throws(function () {\n        parse_file('example_table/malformed_multiline_example_table_1');\n      }, /Dash is unexpected at this time/);\n\n      assert.throws(function () {\n        parse_file('example_table/malformed_multiline_example_table_2');\n      }, /Indentation error/);\n\n      assert.throws(function () {\n        parse_file('example_table/malformed_multiline_example_table_3');\n      }, /Text is unexpected at this time/);\n    });\n\n    it('should add meta fields to multiline example table', function () {\n      var scenarios = parse_file('example_table/meta_fields_multiline_example_table').scenarios;\n      assert.equal(scenarios.length, 2);\n\n      assert.equal(scenarios[0].title, 'Meta Fields Multiline Example Table');\n      assert.equal(scenarios[0].steps.length, 2);\n      assert.equal(scenarios[0].steps[0], '1 left 1 9:5');\n      assert.equal(scenarios[0].steps[1], '1 right 1\\nright 2 9:14');\n\n      assert.equal(scenarios[1].title, 'Meta Fields Multiline Example Table');\n      assert.equal(scenarios[1].steps.length, 2);\n      assert.equal(scenarios[1].steps[0], '2 left 3\\nleft 4 12:5');\n      assert.equal(scenarios[1].steps[1], '2 right 3 12:14');\n    });\n  });\n\n  describe('(Localisation)', function () {\n    it('should support multiple languages', function () {\n      var feature = parse_file('localisation/pirate_feature', Pirate);\n      assert.equal(feature.title, 'Treasure Island');\n\n      var scenarios = feature.scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'The Black Spot');\n      assert.deepEqual(scenarios[0].steps, ['Given A', 'When B', 'Then C']);\n\n      assert(scenarios[1].annotations.brig, 'Localised scenario was not marked as pending');\n    });\n\n    it('should support multiple languages using the options object', function () {\n      var feature = parse_file('localisation/pirate_feature', { language: Pirate });\n      assert.equal(feature.title, 'Treasure Island');\n\n      var scenarios = feature.scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'The Black Spot');\n      assert.deepEqual(scenarios[0].steps, ['Given A', 'When B', 'Then C']);\n\n      assert(scenarios[1].annotations.brig, 'Localised scenario was not marked as pending');\n    });\n\n    it('should support changing the default language', function () {\n      Localisation.default = Pirate;\n      var feature = new FeatureParser().parse(load('localisation/pirate_feature'));\n\n      assert.equal(feature.title, 'Treasure Island');\n\n      var scenarios = feature.scenarios;\n      assert.equal(scenarios.length, 2);\n      assert.equal(scenarios[0].title, 'The Black Spot');\n      assert.deepEqual(scenarios[0].steps, ['Given A', 'When B', 'Then C']);\n\n      assert(scenarios[1].annotations.brig, 'Localised scenario was not marked as pending');\n    });\n\n    it('should report missing translations', function () {\n      var language = new Language('Incomplete', {});\n      assert.throws(function () {\n        parse_file('feature/multiple_features', language);\n      }, /Keyword \"feature\" has not been translated into Incomplete/);\n    });\n  });\n\n  describe('(Feature Backgrounds)', function () {\n    it('should parse feature background', function () {\n      var feature = parse_file('background/feature_with_background');\n      assert.equal(feature.scenarios[0].steps[0], 'Given A');\n    });\n\n    it('shoud parse multiline step background', function () {\n      var scenarios = parse_file('background/background_with_multiline_step').scenarios;\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Simple Scenario');\n      assert.equal(scenarios[0].steps[0], poem);\n      assert.equal(scenarios[0].steps[1], 'Given A');\n    });\n\n    it('should report background annotations', function () {\n      assert.throws(function () {\n        parse_file('background/malformed_background_annotated');\n      }, /Background is unexpected at this time/);\n    });\n  });\n\n  describe('(Comments)', function () {\n    it('should support single line comments', function () {\n      var feature = parse_file('comment/singleline_comment');\n      var scenarios = feature.scenarios;\n      assert.equal(feature.title, 'Single Line Comments Feature');\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Single Line Comments Scenario');\n      assert.deepEqual(scenarios[0].steps, ['Given A', 'When # B', 'Then C #']);\n    });\n\n    it('should parse multiline comments', function () {\n      var feature = parse_file('comment/multiline_comment');\n      var scenarios = feature.scenarios;\n      assert.equal(feature.title, 'Simple Feature');\n      assert.equal(scenarios.length, 1);\n      assert.equal(scenarios[0].title, 'Simple Scenario');\n      assert.deepEqual(scenarios[0].steps, ['Given A', 'When B', 'Then C']);\n    });\n  });\n\n  function parse_file(filename, options) {\n    return new FeatureParser(options).parse(load(filename));\n  }\n\n  function load(filename) {\n    return fs.readFileSync(path.join(__dirname, 'features', filename + '.feature'), 'utf8');\n  }\n\n  var poem = [\n    'Good Times',\n    'May we go our separate ways,',\n    'Finding fortune and new friends.',\n    'But let us not forget these days,',\n    'Or let the good times ever end.',\n    '',\n    'A poet with wiser words than mine,',\n    'Wrote that nothing gold can stay.',\n    \"These are golden days we're in,\",\n    'And so are bound to fade away.',\n  ].join('\\n');\n});\n"
  },
  {
    "path": "test/FileSearchTests.js",
    "content": "'use strict';\n\nvar path = require('../lib/shims').path;\nvar assert = require('assert');\nvar FileSearch = require('../lib/FileSearch');\n\ndescribe('FileSearch', function () {\n  it('should return all files by default', function () {\n    var files = new FileSearch('./test/filesearch').list().sort();\n    assert.equal(files.length, 6);\n    assert.equal(files[0], path.join('test', 'filesearch', 'exclude.js'));\n    assert.equal(files[1], path.join('test', 'filesearch', 'include.feature'));\n    assert.equal(files[2], path.join('test', 'filesearch', 'subdir1', 'exclude.js'));\n    assert.equal(files[3], path.join('test', 'filesearch', 'subdir1', 'include.spec'));\n    assert.equal(files[4], path.join('test', 'filesearch', 'subdir2', 'subdir3', 'exclude.js'));\n    assert.equal(files[5], path.join('test', 'filesearch', 'subdir2', 'subdir3', 'include.specification'));\n  });\n\n  it('should return the matching files when a regex is specified', function () {\n    var files = new FileSearch('./test/filesearch', /.*\\.feature$/).list();\n    assert.equal(files.length, 1);\n    assert.equal(files[0], path.join('test', 'filesearch', 'include.feature'));\n  });\n\n  it('should ignore missing search paths', function () {\n    var files = new FileSearch(['./test/foo', './test/filesearch'], /.*\\.feature$/).list();\n    assert.equal(files.length, 1);\n  });\n});\n"
  },
  {
    "path": "test/FunctionalTests.js",
    "content": "'use strict';\n\nvar Yadda = require('../lib/index').Yadda;\n\ndescribe('Hospital', function () {\n  var yadda;\n\n  beforeEach(function () {\n    var library = require('./lib/hospital-steps').init();\n    yadda = new Yadda(library);\n  });\n\n  it('should admit an on template patient', function () {\n    yadda.yadda(['Given that Bob Holness is a male, cardiovascular patient at Heathroad hospital', 'and that Holbrook ward is a cardiovascular ward in Heathroad hospital', 'and that bed 209 is a male bed in Holbrook ward', 'when Bob is admitted to bed 209', 'then he is marked as on template']);\n  });\n\n  it('should admit an off template patient', function () {\n    yadda.yadda(['Given that Bob Holness is a male, cardiovascular patient at Heathroad hospital', 'and that Bucklesham ward is a respiratory ward in Heathroad hospital', 'and that bed 209 is a male bed in Bucklesham ward', 'when Bob is admitted to bed 209', 'then he is marked as off template']);\n  });\n});\n"
  },
  {
    "path": "test/InterpreterTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Yadda = require('../lib/index');\nvar Interpreter = Yadda.Interpreter;\nvar EventBus = Yadda.EventBus;\nvar Library = Yadda.Library;\nvar Dictionary = Yadda.Dictionary;\nvar Context = Yadda.Context;\nvar Counter = require('./Counter');\n\ndescribe('Interpreter', function () {\n  it('should interpret a single line script', function () {\n    var counter = new Counter();\n    var library = new Library().define('Blah blah blah', counter.count);\n\n    new Interpreter(library).interpret('Blah blah blah');\n\n    assert.equal(counter.total(), 1);\n  });\n\n  it('should interpret a multiline script', function () {\n    var counter = new Counter();\n    var library = new Library().define('Blah blah blah', counter.count);\n\n    new Interpreter(library).interpret(['Blah blah blah', 'Blah blah blah']);\n\n    assert.equal(counter.total(), 2);\n  });\n\n  it('should validate scenarios', function () {\n    var library = new Library()\n      .define('This is defined')\n      .define(/[Tt]his is ambiguous/)\n      .define(/[tT]his is ambiguous/);\n\n    assert.throws(function () {\n      new Interpreter(library).validate(['This is defined', 'This is undefined', 'This is ambiguous']);\n    }, /Scenario cannot be interpreted\\nThis is defined\\nThis is undefined <-- Undefined Step\\nThis is ambiguous <-- Ambiguous Step/);\n  });\n\n  it('should favour ambiguous steps from the same library as the previous step', function () {\n    var library1 = new Library().define('Library 1').define(/[Tt]his is ambiguous/);\n    var library2 = new Library().define('Library 2').define(/[tT]his is ambiguous/);\n\n    new Interpreter([library1, library2]).validate(['Library 2', 'This is ambiguous']);\n  });\n\n  it('should utilise macros from different libraries', function () {\n    var counter = new Counter();\n    var library_1 = new Library().define('Blah blah blah', counter.count);\n    var library_2 = new Library().define('Whatever', counter.count);\n\n    new Interpreter([library_1, library_2]).interpret(['Blah blah blah', 'Whatever']);\n\n    assert.equal(counter.total(), 2);\n  });\n\n  it('should expanded terms to discern macros', function () {\n    var patient_name;\n\n    var dictionary = new Dictionary().define('gender', '(male|female)').define('speciality', '(cardio|elderly care)');\n\n    var library = new Library(dictionary)\n      .define('Given a $gender patient called $name', function (gender, name) {\n        patient_name = name;\n      })\n      .define('Given a $speciality patient called $name', function (speciality, name) {\n        patient_name = name;\n      });\n\n    new Interpreter(library).interpret('Given a female patient called Carol');\n    assert.equal('Carol', patient_name);\n\n    new Interpreter(library).interpret('Given a cardio patient called Bobby');\n    assert.equal('Bobby', patient_name);\n  });\n\n  it('should report undefined steps', function () {\n    var library = new Library();\n    var interpreter = new Interpreter(library);\n\n    assert.throws(function () {\n      interpreter.interpret('Blah blah blah');\n    }, /Undefined Step: \\[Blah blah blah\\]/);\n  });\n\n  it('should interpret steps asynchronously', function (done) {\n    var counter = new Counter();\n    var library = new Library().define('Blah blah blah', counter.count);\n\n    new Interpreter(library).interpret(['Blah blah blah', 'Blah blah blah'], {}, function () {\n      assert.equal(counter.total(), 2);\n      done();\n    });\n  });\n\n  it('should support variadic asynchronous steps', function (done) {\n    var counter = new Counter();\n    var library = new Library().define(\n      ['Blah (blah)', 'Blah (blah) (blah)'],\n      function () {\n        counter.count();\n        arguments[arguments.length - 1]();\n      },\n      {},\n      { mode: 'async' }\n    );\n\n    new Interpreter(library).interpret(['Blah blah', 'Blah blah blah'], {}, function () {\n      assert.equal(counter.total(), 2);\n      done();\n    });\n  });\n\n  it('should bind the context to the macro', function (done) {\n    var context = new Context({ foo: 'bar' });\n    var library = new Library().define('Blah blah blah', function (next) {\n      assert.equal(this.foo, 'bar');\n      next();\n    });\n\n    new Interpreter(library).interpret(['Blah blah blah', 'Blah blah blah'], context, done);\n  });\n\n  it('should notify listeners of interpreter events', function (done) {\n    var library = new Library().define('Blah blah blah');\n    var interpreter = new Interpreter(library);\n    var listener = new Listener();\n    EventBus.instance().on(/STEP|SCENARIO/, listener.listen);\n\n    interpreter.interpret('Blah blah blah', new Context({ foo: 'bar' }));\n\n    assert.equal(2, listener.events.length);\n\n    assert_event(\n      {\n        name: EventBus.ON_SCENARIO,\n        data: { scenario: 'Blah blah blah', ctx: { foo: 'bar' } },\n      },\n      listener.events[0]\n    );\n\n    assert_event(\n      {\n        name: EventBus.ON_STEP,\n        data: { step: 'Blah blah blah', ctx: { foo: 'bar' } },\n      },\n      listener.events[1]\n    );\n\n    done();\n  });\n\n  it('should catch errors thrown by asynchronous steps where possible', function () {\n    var library = new Library().define('Blah blah blah', function (next) {\n      throw new Error('Oh Noes!');\n    });\n\n    new Interpreter(library).interpret('Blah blah blah', {}, function (err) {\n      assert.ok(err);\n      assert.equal(err.message, 'Oh Noes!');\n    });\n  });\n\n  function Listener() {\n    var _this = this;\n    this.events = [];\n    this.listen = function (event) {\n      _this.events.push(event);\n    };\n  }\n\n  function assert_event(expected, actual) {\n    assert.ok(actual);\n    assert.equal(expected.name, actual.name);\n    assert.deepEqual(expected.data, actual.data);\n  }\n});\n"
  },
  {
    "path": "test/LibraryTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Library = require('../lib/index').Library;\nvar English = require('../lib/index').localisation.English;\nvar Dictionary = require('../lib/Dictionary');\nvar fn = require('../lib/fn');\n\ndescribe('Library', function () {\n  it('should hold String mapped macros', function () {\n    var library = new Library().define('foo');\n    assert.ok(library.get_macro('foo'), 'Macro should have been defined');\n    assert.ok(library.get_macro(/foo/), 'Macro should have been defined');\n  });\n\n  it('should hold RegExp mapped macros', function () {\n    var library = new Library().define(/bar/);\n    assert.ok(library.get_macro(/bar/), 'Macro should have been defined');\n    assert.ok(library.get_macro('bar'), 'Macro should have been defined');\n  });\n\n  it('should support aliased macros', function () {\n    var library = new Library().define([/bar/, /foo/]);\n    assert.ok(library.get_macro(/bar/), 'Macro should have been defined');\n    assert.ok(library.get_macro(/foo/), 'Macro should have been defined');\n  });\n\n  it('should hold String mapped macros when options are specified', function () {\n    var library = new Library().define('foo', fn.noop, {}, {});\n    assert.ok(library.get_macro('foo'), 'Macro should have been defined');\n    assert.ok(library.get_macro(/foo/), 'Macro should have been defined');\n  });\n\n  it('should hold RegExp mapped macros when options are specified', function () {\n    var library = new Library().define(/bar/, fn.noop, {}, {});\n\n    assert.ok(library.get_macro(/bar/), 'Macro should have been defined');\n    assert.ok(library.get_macro('bar'), 'Macro should have been defined');\n  });\n\n  it('should support aliased macros when options are specified', function () {\n    var library = new Library().define([/bar/, /foo/], {}, { mode: 'async' });\n    assert.ok(library.get_macro(/bar/), 'Macro should have been defined');\n    assert.ok(library.get_macro(/foo/), 'Macro should have been defined');\n  });\n\n  it('should expand macro signature using specified dictionary', function () {\n    var dictionary = new Dictionary().define('gender', '(male|female)').define('speciality', '(cardiovascular|elderly care)');\n\n    var library = new Library(dictionary).define('Given a $gender, $speciality patient called $name');\n\n    var macro = library.get_macro('Given a $gender, $speciality patient called $name');\n    assert.ok(macro.can_interpret('Given a male, cardiovascular patient called Bob'));\n    assert.ok(macro.can_interpret('Given a female, elderly care patient called Carol'));\n    assert.ok(!macro.can_interpret('Given a ugly, angry patient called Max'));\n  });\n\n  it('should report duplicate macros', function () {\n    var library = English.library().define(/bar/);\n\n    assert.throws(function () {\n      library.define(/bar/);\n    }, /Duplicate macro: \\[\\/bar\\/\\]/);\n  });\n\n  it('should find all compatible macros', function () {\n    var library = new Library()\n      .define(/^food$/)\n      .define(/^foo.*$/)\n      .define(/^f.*$/);\n\n    assert.equal(library.find_compatible_macros('fort').length, 1);\n    assert.equal(library.find_compatible_macros('foodie').length, 2);\n    assert.equal(library.find_compatible_macros('food').length, 3);\n  });\n\n  it('should be localised', function () {\n    var library = English.library()\n      .given(/^a wall with (\\d+) bottles/)\n      .when(/^(\\d+) bottle(?:s)? accidentally falls/)\n      .then(/^there are (\\d+) bottles left/);\n\n    var givens = ['Given a wall with 100 bottles', 'given a wall with 100 bottles', 'And a wall with 100 bottles', 'and a wall with 100 bottles', 'with   a wall with 100 bottles'];\n\n    var whens = ['When 1 bottle accidentally falls', 'when 1 bottle accidentally falls', 'and 1 bottle accidentally falls', 'And 1 bottle accidentally falls', 'but  1 bottle accidentally falls'];\n\n    var thens = ['Then there are 99 bottles left', 'then there are 99 bottles left', 'And there are 99 bottles left', 'and there are 99 bottles left', 'Expect there are 99 bottles left', 'expect there are 99 bottles left', 'but  there are 99 bottles left'];\n\n    assert_localisation(library, givens, '/^(?:\\\\s)*(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)\\\\s+a wall with (\\\\d+) bottles/');\n    assert_localisation(library, whens, '/^(?:\\\\s)*(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)\\\\s+(\\\\d+) bottle(?:s)? accidentally falls/');\n    assert_localisation(library, thens, '/^(?:\\\\s)*(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)\\\\s+there are (\\\\d+) bottles left/');\n  });\n\n  it('should supports localised aliased macros', function () {\n    var library = English.library()\n      .given([/^a wall with (\\d+) bottles/, /^a wall with (\\d+) green bottles/])\n      .when([/^(\\d+) bottle(?:s)? accidentally falls/, /^(\\d+) green bottle(?:s)? accidentally falls/])\n      .then([/^there are (\\d+) bottles left/, /^there are (\\d+) green bottles left/]);\n\n    assert.equal(library.find_compatible_macros('Given a wall with 100 bottles').length, 1);\n    assert.equal(library.find_compatible_macros('Given a wall with 100 green bottles').length, 1);\n    assert.equal(library.find_compatible_macros('When 1 bottle accidentally falls').length, 1);\n    assert.equal(library.find_compatible_macros('When 1 green bottle accidentally falls').length, 1);\n    assert.equal(library.find_compatible_macros('Then there are 99 bottles left').length, 1);\n    assert.equal(library.find_compatible_macros('Then there are 99 green bottles left').length, 1);\n  });\n\n  it('should expand multiline macro signature using specified dictionary', function () {\n    var dictionary = new Dictionary().define('text', /([^\\u0000]*)/);\n\n    var library = new Library(dictionary).define('Given a text $text');\n\n    var macro = library.get_macro('Given a text $text');\n    assert.ok(macro.can_interpret('Given a text ')); // empty\n    assert.ok(macro.can_interpret('Given a text 1')); // oneline\n    assert.ok(macro.can_interpret('Given a text 1\\n2\\n3')); // multiline\n    assert.ok(!macro.can_interpret('Given another thing'));\n  });\n\n  function assert_localisation(library, statements, signature) {\n    for (var i = 0; i < statements.length; i++) {\n      assert.equal(library.find_compatible_macros(statements[i]).length, 1, statements[i]);\n      assert.equal(library.find_compatible_macros(statements[i])[0].toString(), signature, statements[i]);\n    }\n  }\n});\n"
  },
  {
    "path": "test/LocalisationTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Yadda = require('../lib/index');\nvar Interpreter = Yadda.Interpreter;\nvar Counter = require('./Counter');\n\ndescribe('Localisation', function () {\n  it('should match text from the beginning', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.English.library()\n      .given('a post', function () {\n        assert.fail('Step should not have been matched');\n      })\n      .define(/.*/, counter.count);\n\n    new Interpreter(library).interpret(['Given a patient with anxiety and a post-traumatic stress disorder']);\n\n    assert.equal(counter.total(), 1);\n  });\n\n  it('should support English', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.English.library().given('some text 1', counter.count).when('some text 2', counter.count).then('some text 4', counter.count);\n\n    new Interpreter(library).interpret(['given some text 1', 'when some text 2', 'then some text 4']);\n\n    assert.equal(counter.total(), 3);\n  });\n\n  it('should support German', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.German.library().given('some text 1', counter.count).when('some text 2', counter.count).then('some text 4', counter.count);\n\n    new Interpreter(library).interpret(['angenommen some text 1', 'wenn some text 2', 'dann some text 4']);\n\n    assert.equal(counter.total(), 3);\n  });\n\n  it('should support Dutch', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.Dutch.library().given('some text 1', counter.count).when('some text 2', counter.count).then('some text 4', counter.count);\n\n    new Interpreter(library).interpret(['Gegeven dat some text 1', 'Wanneer some text 2', 'Dan some text 4']);\n\n    assert.equal(counter.total(), 3);\n  });\n\n  it('should support French', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.French.library()\n      .soit('some text 1', counter.count)\n      .etantdonnees('some text 2', counter.count)\n      .etantdonnee('some text 3', counter.count)\n      .etantdonne('some text 4', counter.count)\n      .given('some text 5', counter.count)\n\n      .quand('some text 6', counter.count)\n      .lorsque('some text 7', counter.count)\n      .when('some text 8', counter.count)\n\n      .alors('some text 9', counter.count)\n      .then('some text 10', counter.count);\n\n    new Interpreter(library).interpret(['soit some text 1', 'étant données some text 2', 'étant donnée some text 3', 'étant donné some text 4', 'soit some text 5', 'quand some text 6', 'lorsque some text 7', 'quand some text 8', 'alors some text 9', 'alors some text 10']);\n\n    assert.equal(counter.total(), 10);\n  });\n\n  it('should support Norwegian', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.Norwegian.library()\n      .gitt('some text 1', counter.count)\n      .given('some text 2', counter.count)\n\n      .når('some text 3', counter.count)\n      .when('some text 4', counter.count)\n\n      .så('some text 5', counter.count)\n      .then('some text 6', counter.count);\n\n    new Interpreter(library).interpret(['gitt some text 1', 'gitt some text 2', 'når some text 3', 'når some text 4', 'så some text 5', 'så some text 6']);\n\n    assert.equal(counter.total(), 6);\n  });\n\n  it('should support Piracy', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.Pirate.library()\n      .giveth('some text 1', counter.count)\n      .given('some text 2', counter.count)\n\n      .whence('some text 3', counter.count)\n      .when('some text 4', counter.count)\n\n      .thence('some text 5', counter.count)\n      .then('some text 6', counter.count);\n\n    new Interpreter(library).interpret(['giveth some text 1', 'giveth some text 2', 'whence some text 3', 'whence some text 4', 'thence some text 5', 'thence some text 6']);\n\n    assert.equal(counter.total(), 6);\n  });\n\n  it('should support Ukrainian', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.Ukrainian.library().given('some text 1', counter.count).when('some text 2', counter.count).then('some text 3', counter.count);\n\n    new Interpreter(library).interpret(['дано some text 1', 'коли some text 2', 'тоді some text 3']);\n\n    assert.equal(counter.total(), 3);\n  });\n\n  it('should support Polish', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.Polish.library()\n      .zakladajac('some text 1', counter.count)\n      .majac('some text 2', counter.count)\n      .given('some text 3', counter.count)\n\n      .jezeli('some text 4', counter.count)\n      .jesli('some text 5', counter.count)\n      .gdy('some text 6', counter.count)\n      .kiedy('some text 7', counter.count)\n      .when('some text 8', counter.count)\n\n      .wtedy('some text 9', counter.count)\n      .then('some text 10', counter.count);\n\n    new Interpreter(library).interpret(['zakładając some text 1', 'mając some text 2', 'zakładając some text 3', 'jeżeli some text 4', 'jeśli some text 5', 'gdy some text 6', 'kiedy some text 7', 'jeżeli some text 8', 'wtedy some text 9', 'wtedy some text 10']);\n\n    assert.equal(counter.total(), 10);\n  });\n\n  it('should support Spanish', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.Spanish.library()\n      .sea('some text 1', counter.count)\n      .sean('some text 2', counter.count)\n      .dado('some text 3', counter.count)\n      .dada('some text 4', counter.count)\n      .dados('some text 5', counter.count)\n      .dadas('some text 6', counter.count)\n      .given('some text 7', counter.count)\n\n      .cuando('some text 8', counter.count)\n      .si('some text 9', counter.count)\n      .when('some text 10', counter.count)\n\n      .entonces('some text 11', counter.count)\n      .then('some text 12', counter.count);\n\n    new Interpreter(library).interpret(['sea some text 1', 'sean some text 2', 'dado some text 3', 'dada some text 4', 'dados some text 5', 'dadas some text 6', 'sea some text 7', 'cuando some text 8', 'si some text 9', 'cuando some text 10', 'entonces some text 11', 'entonces some text 12']);\n\n    assert.equal(counter.total(), 12);\n  });\n\n  it('should support Russian', function () {\n    var counter = new Counter();\n    var library = Yadda.localisation.Russian.library().given('some text 1', counter.count).when('some text 2', counter.count).then('some text 4', counter.count);\n\n    new Interpreter(library).interpret(['допустим some text 1', 'если some text 2', 'то some text 4']);\n\n    assert.equal(counter.total(), 3);\n  });\n\n  it('should support Portuguese', function () {\n    var counter = new Counter();\n\n    var library = Yadda.localisation.Portuguese.library()\n      .seja('some text 1', counter.count)\n      .sejam('some text 2', counter.count)\n      .dado('some text 3', counter.count)\n      .dada('some text 4', counter.count)\n      .dados('some text 5', counter.count)\n      .dadas('some text 6', counter.count)\n      .given('some text 7', counter.count)\n      .given('some text 8', counter.count)\n      .when('some text 9', counter.count)\n\n      .quando('some text 10', counter.count)\n      .se('some text 11', counter.count)\n      .when('some text 12', counter.count)\n      .when('some text 13', counter.count)\n      .when('some text 14', counter.count)\n\n      .entao('some text 15', counter.count)\n      .then('some text 16', counter.count)\n\n      .entao('some text 17', counter.count)\n      .entao('some text 18', counter.count);\n\n    new Interpreter(library).interpret([\n      'seja some text 1',\n      'sejam some text 2',\n      'dado some text 3',\n      'dada some text 4',\n      'dados some text 5',\n      'dadas some text 6',\n      'seja some text 7',\n      'e some text 8',\n      'mas some text 9',\n\n      'quando some text 10',\n      'se some text 11',\n      'quando some text 12',\n      'e some text 13',\n      'mas some text 14',\n\n      'então some text 15',\n      'entao some text 16',\n      'e some text 17',\n      'mas some text 18',\n    ]);\n\n    assert.equal(counter.total(), 18);\n  });\n});\n"
  },
  {
    "path": "test/MacroTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Macro = require('../lib/Macro');\nvar Context = require('../lib/Context');\nvar EventBus = require('../lib/EventBus');\nvar Dictionary = require('../lib/Dictionary');\nvar $ = require('../lib/Array');\nvar fn = require('../lib/fn');\n\ndescribe('Macro', function () {\n  it('should interpret a synchronous step synchronously', function () {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), execution.fn, { a: 1 }).interpret('Easy as 1, 2, 3', new Context({ b: 2 }));\n\n    assert.ok(execution.executed, 'The step was not executed');\n    assert.equal(execution.args.length, 3);\n    assert.deepEqual(execution.args, [1, 2, 3]);\n    assert.deepEqual(execution.ctx, { a: 1, b: 2, step: 'Easy as 1, 2, 3' });\n  });\n\n  it('should tolerate too many step arguments for synchronous steps', function () {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as 1, 2, 3/), execution.fn, { a: 1 }).interpret('Easy as 1, 2, 3', new Context({ b: 2 }));\n\n    assert.ok(execution.executed, 'The step was not executed');\n    assert.equal(execution.args.length, 0);\n  });\n\n  it('should tolerate too few step arguments for synchronous steps', function () {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d), (\\d)/), execution.fn, { a: 1 }).interpret('Easy as 1, 2, 3, 4', new Context({ b: 2 }));\n\n    assert.ok(execution.executed, 'The step was not executed');\n    assert.equal(execution.args.length, 4);\n  });\n\n  it('should interpret a synchronous step asynchronously', function (done) {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), execution.fn, { a: 1 }).interpret('Easy as 1, 2, 3', new Context({ b: 2 }), function () {\n      assert.ok(execution.executed, 'The step was not executed');\n      assert.equal(execution.args.length, 3);\n      assert.deepEqual(execution.args, [1, 2, 3]);\n      assert.deepEqual(execution.ctx, { a: 1, b: 2, step: 'Easy as 1, 2, 3' });\n      done();\n    });\n  });\n\n  it('should interpret an asynchronous step', function (done) {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), execution.afn, { a: 1 }).interpret('Easy as 1, 2, 3', new Context({ b: 2 }), function () {\n      assert.ok(execution.executed, 'The step was not executed');\n      assert.equal(execution.args.length, 4);\n      assert.deepEqual(execution.args.splice(0, 3), [1, 2, 3]);\n      assert.deepEqual(execution.ctx, { a: 1, b: 2, step: 'Easy as 1, 2, 3' });\n      done();\n    });\n  });\n\n  it('should fail when too few step arguments for asynchronous steps', function (done) {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), 3/), execution.afn, { a: 1 }).interpret('Easy as 1, 2, 3', new Context({ b: 2 }), function (err) {\n      assert.ok(err);\n      done();\n    });\n  });\n\n  it('should fail when too many step arguments for asynchronous steps', function (done) {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d), (\\d)/), execution.afn, { a: 1 }).interpret('Easy as 1, 2, 3, 4', new Context({ b: 2 }), function (err) {\n      assert.ok(err);\n      done();\n    });\n  });\n\n  it('should support variadic async functions', function (done) {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d), (\\d)/), execution.vafn, { a: 1 }, undefined, { mode: 'async' }).interpret('Easy as 1, 2, 3, 4', new Context({ b: 2 }), function () {\n      assert.ok(execution.executed, 'The step was not executed');\n      assert.equal(execution.args.length, 5);\n      assert.deepEqual(execution.args.splice(0, 4), [1, 2, 3, 4]);\n      assert.deepEqual(execution.ctx, { a: 1, b: 2, step: 'Easy as 1, 2, 3, 4' });\n      done();\n    });\n  });\n\n  it('should execute a promisified step', function (done) {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), execution.promise, { a: 1 }).interpret('Easy as 1, 2, 3', new Context({ b: 2 }), function () {\n      assert.ok(execution.executed, 'The step was not executed');\n      assert.equal(execution.args.length, 3);\n      assert.deepEqual(execution.args, [1, 2, 3]);\n      assert.deepEqual(execution.ctx, { a: 1, b: 2, step: 'Easy as 1, 2, 3' });\n      done();\n    });\n  });\n\n  it('should include step name in the context', function () {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), execution.fn, { a: 1 }).interpret('Easy as 1, 2, 3', new Context({ b: 2 }), fn.noop);\n\n    assert.equal(execution.ctx.step, 'Easy as 1, 2, 3');\n  });\n\n  it('should not override step name in the context if explicitly set', function () {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), execution.fn, { a: 1 }).interpret('Easy as 1, 2, 3', new Context({ b: 2, step: 'Do not override' }), fn.noop);\n\n    assert.equal(execution.ctx.step, 'Do not override');\n  });\n\n  it('should provide a signature that can be used to compare levenshtein distance', function () {\n    $([/the quick brown fox/, /the quick.* brown.* fox/, /the quick(.*) brown(?:.*) fox/, /the quick[xyz] brown[^xyz] fox/, /the quick{0,1} brown{1} fox/, /the quick\\d brown\\W fox/]).each(function (pattern) {\n      assert.equal(new Macro('Quick brown fox', parsed_signature(pattern)).levenshtein_signature(), 'the quick brown fox');\n    });\n  });\n\n  it('should default to a no operation function', function (done) {\n    new Macro('blah $a', parsed_signature(/blah (.*)/)).interpret('blah 1', {}, function () {\n      done();\n    });\n  });\n\n  it('should notify listeners of execute events', function (done) {\n    var listener = new Listener();\n\n    EventBus.instance().on(/EXECUTE/, listener.listen);\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), fn.noop, { a: 1 }).interpret('Easy as 1, 2, 3', { b: 2 });\n\n    assert.equal(1, listener.events.length);\n\n    var event = listener.events[0];\n    assert.equal(event.name, EventBus.ON_EXECUTE);\n    assert.equal(event.data.step, 'Easy as 1, 2, 3');\n    assert.deepEqual(event.data.ctx, { a: 1, b: 2, step: 'Easy as 1, 2, 3' });\n    assert.equal(event.data.pattern, '/Easy as (\\\\d), (\\\\d), (\\\\d)/');\n    done();\n  });\n\n  it('should notify listeners of define events', function (done) {\n    var listener = new Listener();\n\n    EventBus.instance().on(/DEFINE/, listener.listen);\n\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), fn.noop, { a: 1 }).interpret('Easy as 1, 2, 3', { b: 2 });\n\n    assert.equal(1, listener.events.length);\n\n    var event = listener.events[0];\n    assert.equal(event.name, EventBus.ON_DEFINE);\n    assert.equal(event.data.pattern, '/Easy as (\\\\d), (\\\\d), (\\\\d)/');\n    done();\n  });\n\n  it('should interpret a multiline', function () {\n    var execution = new Execution();\n\n    new Macro('Easy', parsed_signature(/Easy as ([^\\u0000]*)/), execution.fn, { a: 1 }).interpret('Easy as 1\\n2\\n3', new Context({ b: 2 }), fn.noop);\n\n    assert.ok(execution.executed, 'The step was not executed');\n    assert.deepEqual(execution.args.splice(0, 1), ['1\\n2\\n3']);\n    assert.deepEqual(execution.ctx, { a: 1, b: 2, step: 'Easy as 1\\n2\\n3' });\n  });\n\n  it('should convert parameters', function () {\n    var execution = new Execution();\n\n    new Macro(\n      'Easy',\n      {\n        pattern: /Easy as (\\d), (\\d), (\\d)/,\n        converters: [\n          function (value, cb) {\n            cb(null, value * 2);\n          },\n          function (value, cb) {\n            cb(null, value * 3);\n          },\n          function (value, cb) {\n            cb(null, value * 4);\n          },\n        ],\n      },\n      execution.fn,\n      { a: 1 }\n    ).interpret('Easy as 1, 2, 3', fn.noop);\n\n    assert.ok(execution.executed, 'The step was not executed');\n    assert.deepEqual(execution.args.splice(0, 3), [2, 6, 12]);\n  });\n\n  it('should convert parameters with multi-arg converters', function () {\n    var execution = new Execution();\n\n    new Macro(\n      'Easy',\n      {\n        pattern: /Easy as (\\d), (\\d), (\\d), (\\d)/,\n        converters: [\n          function (value, cb) {\n            cb(null, value * 2);\n          },\n          function (value1, value2, cb) {\n            cb(null, parseInt(value1) + parseInt(value2));\n          },\n          function (value, cb) {\n            cb(null, value * 3);\n          },\n        ],\n      },\n      execution.fn,\n      { a: 1 }\n    ).interpret('Easy as 1, 2, 3, 4', fn.noop);\n\n    assert.ok(execution.executed, 'The step was not executed');\n    assert.deepEqual(execution.args.splice(0, 3), [2, 5, 12]);\n  });\n\n  it('should convert parameters with multi-result converters', function () {\n    var execution = new Execution();\n\n    new Macro(\n      'Easy',\n      {\n        pattern: /Easy as (\\d), (\\d), (\\d), (\\d)/,\n        converters: [\n          function (value, cb) {\n            cb(null, value * 2);\n          },\n          function (value1, value2, cb) {\n            cb(null, parseInt(value1), parseInt(value2), parseInt(value1));\n          },\n          function (value, cb) {\n            cb(null, value * 3);\n          },\n        ],\n      },\n      execution.fn,\n      { a: 1 }\n    ).interpret('Easy as 1, 2, 3, 4', fn.noop);\n\n    assert.ok(execution.executed, 'The step was not executed');\n    assert.deepEqual(execution.args.splice(0, 5), [2, 2, 3, 2, 12]);\n  });\n\n  it('should yield errors when called asynchronously', function () {\n    new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), function (a, b, c, cb) {\n      throw new Error('Oh Noes!');\n    }).interpret('Easy as 1, 2, 3', {}, function (err) {\n      assert.ok(err);\n      assert.equal(err.message, 'Oh Noes!');\n    });\n  });\n\n  it('should throw errors when called synchronously', function () {\n    assert.throws(function () {\n      new Macro('Easy', parsed_signature(/Easy as (\\d), (\\d), (\\d)/), function (a, b, c) {\n        throw new Error('Oh Noes!');\n      }).interpret('Easy as 1, 2, 3', {});\n    }, /Oh Noes!/);\n  });\n\n  function parsed_signature(pattern) {\n    return new Dictionary().define('foo', pattern).expand('$foo');\n  }\n\n  function Execution() {\n    this.executed = false;\n    this.args = undefined;\n    this.ctx = undefined;\n    var _this = this;\n\n    this.fn = function (a, b, c) {\n      _this.executed = true;\n      _this.captureArguments(arguments);\n      _this.ctx = this;\n    };\n    this.afn = function (a, b, c, next) {\n      _this.executed = true;\n      _this.captureArguments(arguments);\n      _this.ctx = this;\n      next();\n    };\n    this.vafn = function () {\n      _this.executed = true;\n      _this.captureArguments(arguments);\n      _this.ctx = this;\n      arguments[arguments.length - 1]();\n    };\n    this.promise = function (a, b, c) {\n      _this.executed = true;\n      _this.captureArguments(arguments);\n      _this.ctx = this;\n      return {\n        then: function (cb) {\n          cb();\n          return {\n            catch: function (cb) {\n              _this.caught = true;\n            },\n          };\n        },\n      };\n    };\n    this.captureArguments = function (args) {\n      _this.args = this.toArray(args);\n    };\n    this.toArray = function (obj) {\n      return [].slice.call(obj, 0);\n    };\n  }\n\n  function Listener() {\n    var _this = this;\n    this.events = [];\n    this.listen = function (event) {\n      _this.events.push(event);\n    };\n  }\n});\n"
  },
  {
    "path": "test/RegularExpressionTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar RegularExpression = require('../lib/RegularExpression');\n\ndescribe('RegularExpression', function () {\n  it('should base equality on underlying RegExp source', function () {\n    assert.ok(new RegularExpression(/abc/).equals(new RegularExpression(/abc/)));\n    assert.ok(new RegularExpression('abc').equals(new RegularExpression('abc')));\n    assert.ok(new RegularExpression(/abc/).equals(new RegularExpression('abc')));\n    assert.ok(new RegularExpression('abc').equals(new RegularExpression(/abc/)));\n  });\n\n  it('should provide matching groups', function () {\n    var words = new RegularExpression(/(\\d+) (\\w+)/g);\n    var groups = words.groups('1 the 2 quick 3 brown 4 fox');\n    assert.equal(groups.length, 8);\n    assert.equal(groups[0], '1');\n    assert.equal(groups[1], 'the');\n    assert.equal(groups[3], 'quick');\n  });\n\n  it('should provide multiline', function () {\n    var words = new RegularExpression(/text: ([^\\u0000]*)/);\n    var groups = words.groups('text: 1\\n2\\n3');\n    assert.equal(groups.length, 1);\n    assert.equal(groups[0], '1\\n2\\n3');\n  });\n});\n"
  },
  {
    "path": "test/StepParserTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar StepParser = require('../lib/index').parsers.StepParser;\n\ndescribe('StepParser', function () {\n  it('should parse steps', function () {\n    var parser = new StepParser();\n    var text = ['Given A', '', '   When B   ', '   ', 'Then C'].join('\\n');\n    var steps = parser.parse(text);\n\n    assert.equal(steps.length, 3);\n    assert.equal(steps[0], 'Given A');\n    assert.equal(steps[1], '   When B   ');\n    assert.equal(steps[2], 'Then C');\n  });\n});\n"
  },
  {
    "path": "test/StringUtilsTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar StringUtils = require('../lib/StringUtils');\n\ndescribe('StringUtils', function () {\n  it('should detect blank strings', function () {\n    assert.ok(StringUtils.isBlank(''));\n    assert.ok(StringUtils.isBlank(' '));\n    assert.ok(StringUtils.isNotBlank('x'));\n    assert.ok(StringUtils.isNotBlank(' x '));\n  });\n\n  it('should return the indentation size', function () {\n    assert.equal(StringUtils.indentation(''), 0);\n    assert.equal(StringUtils.indentation(' '), 1);\n  });\n});\n"
  },
  {
    "path": "test/YaddaTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Library = require('../lib/index').Library;\nvar Yadda = require('../lib/index').Yadda;\n\ndescribe('Yadda', function () {\n  it('should interpret synchronous scenarios', function () {\n    var executions = 0;\n    var library = new Library().define('foo', function () {\n      executions++;\n    });\n    new Yadda(library).yadda('foo');\n    assert.equal(executions, 1);\n  });\n\n  it('should interpret asynchronous scenarios', function (done) {\n    var executions = 0;\n    var library = new Library().define('foo', function (next) {\n      executions++;\n      next();\n    });\n    new Yadda(library).yadda('foo', function (err) {\n      assert.ifError(err);\n      assert.equal(executions, 1);\n      done();\n    });\n  });\n\n  it('should interpret a mix of asynchronous and synchronous scenarios', function (done) {\n    var executions = 0;\n    var library = new Library()\n      .define('foo', function (next) {\n        executions++;\n        next();\n      })\n      .define('bar', function () {\n        executions++;\n      });\n    new Yadda(library).yadda(['foo', 'bar'], function (err) {\n      assert.ifError(err);\n      assert.equal(executions, 2);\n      done();\n    });\n  });\n\n  it('should interpret asynchronous returning promises', function (done) {\n    var executions = 0;\n    var library = new Library().define('foo', function () {\n      executions++;\n      return {\n        then: function (cb) {\n          cb();\n          return {\n            catch: function () {},\n          };\n        },\n      };\n    });\n    new Yadda(library).yadda('foo', function (err) {\n      assert.ifError(err);\n      assert.equal(executions, 1);\n      done();\n    });\n  });\n\n  it('should interpret asynchronous returning promises', function (done) {\n    var executions = 0;\n    var library = new Library().define('foo', function () {\n      executions++;\n      return {\n        then: function (cb) {\n          cb();\n          return {\n            catch: function () {},\n          };\n        },\n      };\n    });\n    new Yadda(library).yadda('foo', function (err) {\n      assert.ifError(err);\n      assert.equal(executions, 1);\n      done();\n    });\n  });\n\n  it('should cater for people who dont find the recursive api amusing', function () {\n    var Yadda = require('../lib/index');\n    var executions = 0;\n    var library = new Yadda.Library().define('foo', function () {\n      executions++;\n    });\n    var yadda = Yadda.createInstance(library);\n    yadda.run('foo');\n    assert.equal(executions, 1);\n  });\n\n  it('should interpret asynchronous variadic steps', function (done) {\n    var executions = 0;\n    var library = new Library().define(\n      'foo',\n      function () {\n        var next = arguments[arguments.length - 1];\n        assert.equal(typeof next, 'function');\n        executions++;\n        next();\n      },\n      {},\n      { mode: 'async' }\n    );\n    new Yadda(library).yadda('foo', function (err) {\n      assert.ifError(err);\n      assert.equal(executions, 1);\n      done();\n    });\n  });\n\n  it('should interpret asynchronous localised variadic steps', function (done) {\n    var executions = 0;\n    var English = require('../lib').localisation.English;\n    var library = new English.library().given(\n      'foo',\n      function () {\n        var next = arguments[arguments.length - 1];\n        assert.equal(typeof next, 'function');\n        executions++;\n        next();\n      },\n      {},\n      { mode: 'async' }\n    );\n\n    new Yadda(library).yadda('Given foo', function (err) {\n      assert.ifError(err);\n      assert.equal(executions, 1);\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/converters/DateConverterTest.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar convert = require('../../lib/converters/date-converter');\n\ndescribe('Date Converter', function () {\n  it('Should convert strings to date', function (next) {\n    convert('2015-07-24T09:23:31.283Z', function (err, value) {\n      assert.ifError(err);\n      assert.equal(value.toISOString(), '2015-07-24T09:23:31.283Z');\n      next();\n    });\n  });\n\n  it('Should error on invalid date', function (next) {\n    convert('a', function (err, value) {\n      assert(err);\n      assert.equal(err.message, 'Cannot convert [a] to a date');\n      next();\n    });\n  });\n});\n"
  },
  {
    "path": "test/converters/FloatConverterTest.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar convert = require('../../lib/converters/float-converter');\n\ndescribe('Float Converter', function () {\n  it('Should convert strings to float', function (next) {\n    convert('1.1', function (err, value) {\n      assert.ifError(err);\n      assert.equal(value, 1.1);\n      assert.equal(typeof value, 'number');\n      next();\n    });\n  });\n\n  it('Should error on NaN', function (next) {\n    convert('a', function (err, value) {\n      assert(err);\n      assert.equal(err.message, 'Cannot convert [a] to a float');\n      next();\n    });\n  });\n});\n"
  },
  {
    "path": "test/converters/IntegerConverterTest.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar convert = require('../../lib/converters/integer-converter');\n\ndescribe('Integer Converter', function () {\n  it('Should convert strings to integers', function (next) {\n    convert('1', function (err, value) {\n      assert.ifError(err);\n      assert.equal(value, 1);\n      assert.equal(typeof value, 'number');\n      next();\n    });\n  });\n\n  it('Should error on NaN', function (next) {\n    convert('a', function (err, value) {\n      assert(err);\n      assert.equal(err.message, 'Cannot convert [a] to an integer');\n      next();\n    });\n  });\n});\n"
  },
  {
    "path": "test/converters/ListConverterTest.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar convert = require('../../lib/converters/list-converter');\n\ndescribe('List Converter', function () {\n  it('Should convert strings to lists', function (next) {\n    convert('a\\nb\\nc', function (err, value) {\n      assert.ifError(err);\n      assert.deepEqual(value, ['a', 'b', 'c']);\n      next();\n    });\n  });\n});\n"
  },
  {
    "path": "test/converters/TableConverterTest.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar convert = require('../../lib/converters/table-converter');\n\ndescribe('Table Converter', function () {\n  it('Should convert strings to data tables', function (next) {\n    var text = ['left | right', '1    | 3', '2    | 4'].join('\\n');\n\n    convert(text, function (err, value) {\n      assert.ifError(err);\n      assert.equal(value.length, 2);\n      assert.deepEqual(value[0], { left: '1', right: '3' });\n      assert.deepEqual(value[1], { left: '2', right: '4' });\n      next();\n    });\n  });\n\n  it('Should maintain indentation', function (next) {\n    var text = ['left | middle | right', '  1  |   2    |   3  '].join('\\n');\n\n    convert(text, function (err, value) {\n      assert.ifError(err);\n      assert.equal(value.length, 1);\n      assert.deepEqual(value[0], { left: '  1', middle: '  2', right: '  3' });\n      next();\n    });\n  });\n\n  it('Should support multiline rows', function (next) {\n    var text = [\n      'Henry V                     | Romeo and Juliet',\n      '----------------------------|------------------------',\n      'Once more unto the          | What light from yonder',\n      'breech dear friends         | window breaks',\n      '----------------------------|------------------------',\n      'And sheathed their          | It is the East',\n      'swords for lack of argument | and Juliet is the sun',\n    ].join('\\n');\n\n    convert(text, function (err, value) {\n      assert.ifError(err);\n      assert.equal(value.length, 2);\n      assert.deepEqual(value[0], { 'Henry V': 'Once more unto the\\nbreech dear friends', 'Romeo and Juliet': 'What light from yonder\\nwindow breaks' });\n      assert.deepEqual(value[1], { 'Henry V': 'And sheathed their\\nswords for lack of argument', 'Romeo and Juliet': 'It is the East\\nand Juliet is the sun' });\n      next();\n    });\n  });\n\n  it('Should maintain indentation for multiline rows', function (next) {\n    var text = [\n      'Henry V                       | Romeo and Juliet',\n      '------------------------------|------------------------',\n      '  Once more unto the          |  What light from yonder',\n      '                              |  ',\n      '  breech dear friends         |  window breaks',\n      '------------------------------|------------------------',\n      '  And sheathed their          |  It is the East',\n      '  swords for lack of argument |  and Juliet is the sun',\n    ].join('\\n');\n\n    convert(text, function (err, value) {\n      assert.ifError(err);\n      assert.equal(value.length, 2);\n      assert.deepEqual(value[0], { 'Henry V': '  Once more unto the\\n\\n  breech dear friends', 'Romeo and Juliet': ' What light from yonder\\n\\n window breaks' });\n      assert.deepEqual(value[1], { 'Henry V': '  And sheathed their\\n  swords for lack of argument', 'Romeo and Juliet': ' It is the East\\n and Juliet is the sun' });\n      next();\n    });\n  });\n\n  it('Should support outer borders', function (next) {\n    var text = [\n      ' Henry V                     | Romeo and Juliet       |',\n      '-----------------------------|------------------------|',\n      ' Once more unto the          | What light from yonder |',\n      ' breech dear friends         | window breaks          |',\n      '-----------------------------|------------------------|',\n      ' And sheathed their          | It is the East         |',\n      ' swords for lack of argument | and Juliet is the sun  |',\n    ].join('\\n');\n\n    convert(text, function (err, value) {\n      assert.ifError(err);\n      assert.equal(value.length, 2);\n      assert.deepEqual(value[0], { 'Henry V': 'Once more unto the\\nbreech dear friends', 'Romeo and Juliet': 'What light from yonder\\nwindow breaks' });\n      assert.deepEqual(value[1], { 'Henry V': 'And sheathed their\\nswords for lack of argument', 'Romeo and Juliet': 'It is the East\\nand Juliet is the sun' });\n      next();\n    });\n  });\n\n  it('Should report indentation errors', function (next) {\n    var text = ['left | middle | right', '  1  |2       |   3  '].join('\\n');\n\n    convert(text, function (err, value) {\n      assert(err);\n      assert.equal(err.message, 'Indentation error');\n      next();\n    });\n  });\n});\n"
  },
  {
    "path": "test/features/annotated/annotated_example_table.feature",
    "content": "@Only\nScenario: [nth] Scenario\n\n    Step [letter][number][number]\n    Step [number][letter][letter]\n\nExamples:\n    nth    | letter | number\n@Pending\n    First  | A      | 1\n    Second | B      | 2\n@Pending\n    Third  | C      | 3\n\n@Crystal\nScenario: Another Scenario\n\n    Step whatever"
  },
  {
    "path": "test/features/annotated/annotated_feature.feature",
    "content": "@keyword1=value1\n    @keyword2=value2\n@keyword3\nFeature: Annotated Feature\nScenario: Simple Scenario\n\nGiven A\nWhen B\nThen C"
  },
  {
    "path": "test/features/annotated/annotated_feature_non_alphanumeric.feature",
    "content": "@KeyWord+1=value1\nFeature: Annotated Feature\n\n@KeyWord-1=value1\nScenario: Simple Scenario\n\nGiven A\nWhen B\nThen C"
  },
  {
    "path": "test/features/annotated/annotated_multiline_example_table.feature",
    "content": "@Only\nScenario: [nth] Scenario\n\n    Step [letter][number][number]\n    Step [number][letter][letter]\n\nExamples:\n    nth    | letter | number\n    -------|--------|-------\n@Pending\n    First  | A      | 1\n    -------|--------|-------\n    Second | B      | 2\n    -------|--------|-------\n@Pending\n    Third  | C      | 3\n\n@Crystal\nScenario: Another Scenario\n\n    Step whatever"
  },
  {
    "path": "test/features/annotated/annotated_scenario.feature",
    "content": "@keyword1=value1\n@keyword2=value2\n@keyword3\nScenario: Annotated Simple Scenario\n\nGiven A\nWhen B\nThen C"
  },
  {
    "path": "test/features/annotated/annotated_scenario_after_background.feature",
    "content": "Feature: Annotation after background bug\n\nBackground: Some Background\n\n    Given A\n\n@keyword1=value1\nScenario: Simple Scenario\n\n    Given A\n    When B\n    Then C"
  },
  {
    "path": "test/features/annotated/untrimmed_annotated_feature.feature",
    "content": "@keyword1= value1 \n@keyword2 = value2 \n@keyword3 \nFeature: Untrimmed Annotated Feature\nScenario: Simple Scenario\n\nGiven A\nWhen B\nThen C"
  },
  {
    "path": "test/features/annotated/untrimmed_annotated_scenario.feature",
    "content": "Feature: Simple Feature\n\n@keyword1= value1 \n@keyword2 = value2 \n@keyword3 \nScenario: Untrimmed Annotated Scenario\n\nGiven A\nWhen B\nThen C"
  },
  {
    "path": "test/features/background/background_with_multiline_step.feature",
    "content": "Feature: Simple Feature With Background\n\n  Background: Multiline Step Background\n\n    Good Times\n    ----------\n    May we go our separate ways,\n    Finding fortune and new friends.\n    But let us not forget these days,\n    Or let the good times ever end.\n\n    A poet with wiser words than mine,\n    Wrote that nothing gold can stay.\n    These are golden days we're in,\n    And so are bound to fade away.\n\n  Scenario: Simple Scenario\n\n    Given A\n    When B\n    Then C"
  },
  {
    "path": "test/features/background/feature_with_background.feature",
    "content": "Feature: Simple Feature With Background\n\n  Background: Simple Background\n\n    Given A\n\n  Scenario: Simple Scenario\n\n    Given B\n    When C\n    Then D"
  },
  {
    "path": "test/features/background/malformed_background_annotated.feature",
    "content": "Feature: Simple Feature\n\n@keyword1=value1\n@keyword2=value2\n@keyword3\nBackground: Annotated Background\n\n    Given A\n\nScenario: Simple Scenario\n\n    Given A\n    When B\n    Then C"
  },
  {
    "path": "test/features/comment/multiline_comment.feature",
    "content": "###\nMulti Line Comment\nBefore Feature\n###\n\nFeature: Simple Feature\n\n#####\nMulti Line Comment\nBefore Scenario\n#####\nScenario: Simple Scenario\n\n    Given A\n\n    #####\n    Muli Line Comment\n    Before Step\n    #####\n\n    When B\n\n    Then C"
  },
  {
    "path": "test/features/comment/singleline_comment.feature",
    "content": "Feature: Single Line Comments Feature\n# Nothing to see here\n## Or here\nScenario: Single Line Comments Scenario\n # Or here\n\n Given A\n When # B\n Then C #"
  },
  {
    "path": "test/features/example_table/complex_multiline_example_table.feature",
    "content": "Scenario: Complex Multiline Example Table\n\n    Step [c1]\n    Step [c2]\n\nExamples:\n\n  c1    | c2\n  ------|------\n  x {   | foo\n    y   |\n   }    |\n        |\n  ------|------\n        | x {\n        |   y\n        |  }\n        |\n\n"
  },
  {
    "path": "test/features/example_table/example_table.feature",
    "content": "Scenario: [nth] Scenario\n\n    Step [letter][number][number]\n    Step [number][letter][letter]\n\nExamples:\n    nth    | letter | number\n    First  | A      | 1\n    Second | B      | 2"
  },
  {
    "path": "test/features/example_table/example_table_2506.feature",
    "content": "Scenario: [nth] Scenario\n\n    Step [letter][number][number]\n    Step [number][letter][letter]\n\nExamples:\n    nth    ┆ letter ┆ number\n    First  ┆ A      ┆ 1\n    Second ┆ B      ┆ 2"
  },
  {
    "path": "test/features/example_table/example_table_followed_by_annotated_scenario.feature",
    "content": "Scenario: Malformed Example Table 4\n\n    Step [letter][number][number]\n    Step [number][letter][letter]\n\nExamples:\n    nth    | letter | number\n    First  | A      | 1\n    Second | B      | 2\n\n@Pending\nScenario: Annotated Scenario\n    Some step"
  },
  {
    "path": "test/features/example_table/example_table_with_chevrons.feature",
    "content": "Scenario: <nth> Scenario\n\n    Step <letter><number><number>\n    Step <number><letter><letter>\n\nExamples:\n    nth    | letter | number\n    First  | A      | 1\n    Second | B      | 2"
  },
  {
    "path": "test/features/example_table/example_table_with_outer_borders.feature",
    "content": "Scenario: [nth] Scenario\n\n    Step [letter][number][number]\n    Step [number][letter][letter]\n\nExamples:\n    ----------------------------\n    | nth    | letter | number |\n    | First  | A      | 1      |\n    | Second | B      | 2      |\n    ----------------------------"
  },
  {
    "path": "test/features/example_table/feature_with_background_and_example_table.feature",
    "content": "Feature: Simple Feature With Examples\n\nBackground:\n\n    BG [letter][number]\n\nScenario: Scenario 1\n\n    Step [letter][number]\n\n    Examples:\n        nth    | letter | number\n        First  | A      | 1\n        Second | B      | 2\n\nScenario: Scenario 2\n\n    Step [number][letter]\n\n    Examples:\n        nth    | letter | number\n        First  | X      | 3\n        Second | Y      | 4"
  },
  {
    "path": "test/features/example_table/incomplete_example_table_1.feature",
    "content": "Scenario: Incomplete Example Table 1\n\n    Given A\n    When B\n    Then C\n\n    Where:"
  },
  {
    "path": "test/features/example_table/incomplete_example_table_2.feature",
    "content": "Scenario: Incomplete Example Table 2\n\n    Step A\n\n    Where:\n\n        Name | Age"
  },
  {
    "path": "test/features/example_table/incomplete_example_table_3.feature",
    "content": "Scenario: Incomplete Example Table 3\n\n    Given A\n    When B\n    Then C\n\n    Where:\n\n        Name | Age\n\n\nScenario: Another Scenario\n\n    Given A\n    When B\n    Then C\n"
  },
  {
    "path": "test/features/example_table/incomplete_example_table_4.feature",
    "content": "Scenario: Incomplete Example Table 4\n\n    Given A\n    When B\n    Then C\n\n    Where:\n\n        Name | Age\n\n\n@Pending\nScenario: Another Scenario\n\n    Given A\n    When B\n    Then C\n"
  },
  {
    "path": "test/features/example_table/malformed_example_table_1.feature",
    "content": "Scenario: Malformed Example  Table 1\n\n    Blah\n\nExamples:\n    One | Two | Three\n    1   | 2   | 3     | 4"
  },
  {
    "path": "test/features/example_table/malformed_example_table_2.feature",
    "content": "Scenario: Malformed Example Table 2\n\n    Step [letter][number][number]\n    Step [number][letter][letter]\n\nExamples:\n    nth    | letter | number\n@Pending\n\n    First  | A      | 1\n    Second | B      | 2"
  },
  {
    "path": "test/features/example_table/malformed_example_table_3.feature",
    "content": "Scenario: Malformed Example Table 3\n\n    Step [letter][number][number]\n    Step [number][letter][letter]\n\nExamples:\n    nth    | letter | number\n    First  | A      | 1\n    Second | B      | 2\n\nA step without a scenario"
  },
  {
    "path": "test/features/example_table/malformed_multiline_example_table_1.feature",
    "content": "Scenario: Malformed Multiline Example Table 1\n\n    Step [c1]\n    Step [c2]\n\nExamples:\n    c1     | c2\n    -------|--------\n    left 1 | right 1\n           | right 2\n@Pending\n    -------|--------\n    left 1 | right 1\n    left 2 |\n"
  },
  {
    "path": "test/features/example_table/malformed_multiline_example_table_2.feature",
    "content": "Scenario: Malformed Multiline Example Table 2\n\n    Step [c1]\n    Step [c2]\n\nExamples:\n    c1     | c2\n    -------|-------\n    left 1 |right 1\n"
  },
  {
    "path": "test/features/example_table/malformed_multiline_example_table_3.feature",
    "content": "Scenario: Malformed Multiline Example Table 3\n\n    Step [c1]\n    Step [c2]\n\nExamples:\n    c1     | c2\n    left 1 | right 1\n           | right 2\n    -------|--------\n    left 1 | right 1\n    left 2 |\n"
  },
  {
    "path": "test/features/example_table/meta_fields.feature",
    "content": "Scenario: [nth] Scenario\n\n    [nth.index] [nth] [nth.start.line]:[nth.start.column]\n    [letter.index] [letter] [letter.start.line]:[letter.start.column]\n    [number.index] [number] [number.start.line]:[number.start.column]\n\nExamples:\n    nth    | letter | number\n    First  | A      | 1\n    Second | B      | 2"
  },
  {
    "path": "test/features/example_table/meta_fields_multiline_example_table.feature",
    "content": "Scenario: Meta Fields Multiline Example Table\n\n    [c1.index] [c1] [c1.start.line]:[c1.start.column]\n    [c2.index] [c2] [c2.start.line]:[c2.start.column]\n\nExamples:\n    c1     | c2\n    -------|--------\n    left 1 | right 1\n           | right 2\n    -------|--------\n    left 3 | right 3\n    left 4 |\n"
  },
  {
    "path": "test/features/example_table/multiline_example_table_with_outer_border.feature",
    "content": "Scenario: Multiline Example Table With Outer Border\n\n    Step [c1]\n    Step [c2]\n\nExamples:\n\n    ┆------------------┆\n    | c1     | c2      |\n    |--------|---------|\n    | left 1 | right 1 |\n    |        | right 2 |\n    ┆--------┆---------┆\n    | left 3 | right 3 |\n    | left 4 |         |\n    ┆------------------┆\n"
  },
  {
    "path": "test/features/example_table/multiline_step_example_table.feature",
    "content": "Scenario: [nth] Scenario\n\n    Step\n    ---\n    [letter][number][number]\n    [number][letter][letter]\n    ---\n\nExamples:\n    nth    | letter | number\n    First  | A      | 1\n    Second | B      | 2"
  },
  {
    "path": "test/features/example_table/simple_multiline_example_table.feature",
    "content": "Scenario: Simple Multiline Example Table\n\n    Step [c1]\n    Step [c2]\n\nExamples:\n    c1     | c2\n    -------|--------\n    left 1 | right 1\n           | right 2\n    -------|--------\n    left 3 | right 3\n    left 4 |\n"
  },
  {
    "path": "test/features/feature/feature_description.feature",
    "content": "Feature: Feature Description\nAs a wood chopper\nI want to maintain a sharp axe\nSo that I can chop wood\n\nScenario: Simple Scenario\n\n    Given A\n    When B\n    Then C"
  },
  {
    "path": "test/features/feature/incomplete_feature.feature",
    "content": "Feature: Create new Sales order"
  },
  {
    "path": "test/features/feature/multiple_features.feature",
    "content": "Feature: First Feature\n\nScenario: Sceanrio For Feature 1\n\nFeature: Second feature"
  },
  {
    "path": "test/features/feature/simple_feature.feature",
    "content": "Feature: Simple Feature\n\nScenario: Simple Scenario\n\n    Given A\n    When B\n    Then C"
  },
  {
    "path": "test/features/localisation/pirate_feature.feature",
    "content": "Tale: Treasure Island\n\nAdventure: The Black Spot\n\n    Given A\n    When B\n    Then C\n\n@Brig\nSortie: Captain Silver\n\n    Given A\n    When B\n    Then C\n"
  },
  {
    "path": "test/features/scenario/complex_scenario.feature",
    "content": "Scenario: Complex Scenario\n\n   Given A\nWhen B\n\n   Then C"
  },
  {
    "path": "test/features/scenario/incomplete_scenario_1.feature",
    "content": "Scenario: Has No Steps"
  },
  {
    "path": "test/features/scenario/incomplete_scenario_2.feature",
    "content": "Scenario: Has No Steps\n\nScenario: Has Steps\n    Step A"
  },
  {
    "path": "test/features/scenario/incomplete_scenario_3.feature",
    "content": "Scenario: Has No Steps\n\n@Pending\nScenario: Has Steps\n    Step A"
  },
  {
    "path": "test/features/scenario/incomplete_scenario_4.feature",
    "content": "Scenario: Has No Steps\n\nExamples:\n    Name  | Age\n    steve | 90"
  },
  {
    "path": "test/features/scenario/malformed_multiline_scenario_1.feature",
    "content": "Scenario: Malformed Multiline Step - No leading step\n\n----------\nMay we go our separate ways,\nFinding fortune and new friends.\nBut let us not forget these days,\nOr let the good times ever end.\n\nA poet with wiser words than mine,\nWrote that nothing gold can stay.\nThese are golden days we're in,\nAnd so are bound to fade away.\n"
  },
  {
    "path": "test/features/scenario/malformed_multiline_scenario_2.feature",
    "content": "Scenario: Multiline Step - Inconsistent Indentation\n\n    Good Times\n    ----------\n May we go our separate ways,\n    Finding fortune and new friends.\n    But let us not forget these days,\n    Or let the good times ever end.\n\n    A poet with wiser words than mine,\n    Wrote that nothing gold can stay.\n    These are golden days we're in,\n    And so are bound to fade away.\n    ----------"
  },
  {
    "path": "test/features/scenario/malformed_multiline_scenario_3.feature",
    "content": "Scenario: Malformed Multiline Step - double dash\n\nStep\n----------\n----------\n"
  },
  {
    "path": "test/features/scenario/malformed_multiline_scenario_4.feature",
    "content": "Scenario: Malformed Multiline Step - dash example\n\nStep\n----------\n\nWhere:\n  foo\n  A\n"
  },
  {
    "path": "test/features/scenario/malformed_multiline_scenario_5.feature",
    "content": "Scenario: Malformed Multiline Step - dash annotation\n\nStep\n----------\n\n@Pending\nScenario: Foo\n\nStep bar\n"
  },
  {
    "path": "test/features/scenario/missing_scenario.feature",
    "content": "Given A\nWhen B\nThen C"
  },
  {
    "path": "test/features/scenario/multiline_step_scenario.feature",
    "content": "Scenario: Multiline Step\n\nGood Times\n----------\nMay we go our separate ways,\nFinding fortune and new friends.\nBut let us not forget these days,\nOr let the good times ever end.\n\nA poet with wiser words than mine,\nWrote that nothing gold can stay.\nThese are golden days we're in,\nAnd so are bound to fade away.\n"
  },
  {
    "path": "test/features/scenario/multiline_step_scenario_with_ending_dash.feature",
    "content": "Scenario: Multiline Step With Ending Dash\n\nGood Times\n----------\nMay we go our separate ways,\nFinding fortune and new friends.\nBut let us not forget these days,\nOr let the good times ever end.\n\nA poet with wiser words than mine,\nWrote that nothing gold can stay.\nThese are golden days we're in,\nAnd so are bound to fade away.\n----------"
  },
  {
    "path": "test/features/scenario/multiline_step_scenario_with_followers.feature",
    "content": "Scenario: Multiline Step Followed By Scenario\n\n    Good Times\n    ----------\n    May we go our separate ways,\n    Finding fortune and new friends.\n    But let us not forget these days,\n    Or let the good times ever end.\n\n    A poet with wiser words than mine,\n    Wrote that nothing gold can stay.\n    These are golden days we're in,\n    And so are bound to fade away.\n    ----------\n\nScenario: Another scenario\n\n    Yadda, yadda, yadda\n\n\nScenario: Multiline Step Followed By Annotation\n\n    Good Times\n    ----------\n    May we go our separate ways,\n    Finding fortune and new friends.\n    But let us not forget these days,\n    Or let the good times ever end.\n\n    A poet with wiser words than mine,\n    Wrote that nothing gold can stay.\n    These are golden days we're in,\n    And so are bound to fade away.\n\n\n@Pending\nScenario: Another scenario\n\n    Yadda, yadda, yadda\n\n\nScenario: Multiline Step Followed By Example Table\n\n    Good Times\n    ----------\n    May we go our separate ways,\n    Finding fortune and new friends.\n    But let us not forget these days,\n    Or let the good times ever end.\n\n    A poet with wiser words than mine,\n    Wrote that nothing gold can stay.\n    These are golden days we're in,\n    And so are bound to fade away.\n\nWhere:\n\n    Foo | Bar\n    A   | B\n"
  },
  {
    "path": "test/features/scenario/multiline_step_scenario_with_indentation.feature",
    "content": "Scenario: Multiline Step With Indentation\n\n  LOLCODE\n  ---------\n  HAI\n  CAN HAS STDIO?\n  PLZ OPEN FILE \"LOLCATS.TXT\"?\n      AWSUM THX\n          VISIBLE FILE\n      O NOES\n          INVISIBLE \"ERROR!\"\n  KTHXBYE\n"
  },
  {
    "path": "test/features/scenario/multiline_step_scenario_with_multiple_blocks.feature",
    "content": "Scenario: Multiline Step With Multiple Blocks\n\n    Verse 1\n    ----------\n    May we go our separate ways,\n    Finding fortune and new friends.\n    But let us not forget these days,\n    Or let the good times ever end.\n    -----------\n\n    Verse 2\n    ----------\n    A poet with wiser words than mine,\n    Wrote that nothing gold can stay.\n    These are golden days we're in,\n    And so are bound to fade away.\n    ----------\n"
  },
  {
    "path": "test/features/scenario/multiline_step_scenario_with_multiple_blocks_and_blank.feature",
    "content": "Scenario: Multiline Step With Multiple Blocks And Blank\n\n    Verse 1\n    ----------\n    May we go our separate ways,\n    Finding fortune and new friends.\n    But let us not forget these days,\n    Or let the good times ever end.\n\n    -----------\n\n    Verse 2\n    ----------\n    A poet with wiser words than mine,\n    Wrote that nothing gold can stay.\n    These are golden days we're in,\n    And so are bound to fade away.\n\n    ----------\n"
  },
  {
    "path": "test/features/scenario/multiple_scenarios.feature",
    "content": "Feature: Simple Feature\n\nScenario: First Scenario\n\n    Given A\n    When B\n    Then C\n\nScenario: Second Scenario\n\n    Given X\n    When Y\n    Then Z\n"
  },
  {
    "path": "test/features/scenario/simple_scenario.feature",
    "content": "Scenario: Simple Scenario\nGiven A\nWhen B\nThen C"
  },
  {
    "path": "test/filesearch/exclude.js",
    "content": "'use strict';\n\nmodule.exports = {\n  // exclude this\n};\n"
  },
  {
    "path": "test/filesearch/include.feature",
    "content": "include.feature"
  },
  {
    "path": "test/filesearch/subdir1/exclude.js",
    "content": "'use strict';\n\nmodule.exports = {\n  // exclude this\n};\n"
  },
  {
    "path": "test/filesearch/subdir1/include.spec",
    "content": "include.spec"
  },
  {
    "path": "test/filesearch/subdir2/subdir3/exclude.js",
    "content": "'use strict';\n\nmodule.exports = {\n  // exclude this\n};\n"
  },
  {
    "path": "test/filesearch/subdir2/subdir3/include.specification",
    "content": "include.specification"
  },
  {
    "path": "test/lib/hospital-steps.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar Dictionary = require('../../lib/index').Dictionary;\nvar English = require('../../lib/index').localisation.English;\nvar Hospital = require('./hospital').Hospital;\nvar Patient = require('./hospital').Patient;\nvar Ward = require('./hospital').Ward;\nvar Bed = require('./hospital').Bed;\n\nmodule.exports.init = function () {\n  var hospital, ward, patient, bed;\n  var dictionary = new Dictionary()\n    .define('gender', /(male|femail)/)\n    .define('speciality', /(cardiovascular|respiratory)/)\n    .define('x', /(a) (b)/);\n\n  var library = English.library(dictionary)\n\n    .given('that $name is a $gender, $speciality patient at $hospital hospital', function (patient_name, gender, speciality, hospital_name) {\n      hospital = hospital ? hospital : new Hospital(hospital_name);\n      patient = hospital.admit(new Patient(patient_name));\n      patient.gender = gender;\n      patient.speciality = speciality;\n    })\n    .given('that $ward ward is a $speciality ward in $hospital hospital', function (ward_name, speciality, hospital_name) {\n      hospital = hospital ? hospital : new Hospital(hospital_name);\n      ward = hospital.is_ward(ward_name) ? hospital.get_ward(ward_name) : hospital.add_ward(new Ward(ward_name));\n      ward.speciality = speciality;\n    })\n    .given('that bed $number is a $gender bed in $ward ward', function (number, gender, ward_name) {\n      bed = ward.get_bed(number) ? ward.get_bed(number) : ward.add_bed(new Bed(ward, number));\n      bed.gender = gender;\n    })\n    .when('$name is admitted to bed $number', function (name, number) {\n      name.match(/he|she/) ? patient : hospital.get_patient(name);\n      bed = hospital.get_bed(number);\n      bed.admit(patient);\n    })\n    .then('$name is marked as $template template', function (name, template) {\n      patient = name.match(/he|she/) ? patient : hospital.get_patient(name);\n      assert.equal(patient.template, template);\n    });\n\n  return library;\n};\n"
  },
  {
    "path": "test/lib/hospital.js",
    "content": "'use strict';\n\nvar Patient = function (full_name) {\n  this.first_name = full_name.split(' ')[0];\n  this.last_name = full_name.split(' ')[1];\n  this.full_name = full_name;\n  this.gender;\n  this.speciality;\n  this.template;\n};\n\nvar Hospital = function (name) {\n  this.name = name;\n  this.patients = {};\n  this.wards = {};\n\n  this.add_ward = function (ward) {\n    this.wards[ward.name] = ward;\n    return ward;\n  };\n\n  this.is_ward = function (name) {\n    return this.get_ward(name) !== undefined;\n  };\n\n  this.admit = function (patient) {\n    this.patients[patient.first_name] = patient;\n    this.patients[patient.full_name] = patient;\n    return patient;\n  };\n\n  this.is_admitted = function (name) {\n    return this.get_patient(name) !== undefined;\n  };\n\n  this.get_patient = function (name) {\n    return this.patients[name];\n  };\n\n  this.get_ward = function (name) {\n    return this.wards[name];\n  };\n\n  this.get_bed = function (number) {\n    var bed;\n    for (var ward in this.wards) {\n      bed = this.wards[ward].get_bed(number);\n      if (bed) break;\n    }\n    return bed;\n  };\n};\n\nvar Ward = function (name) {\n  this.name = name;\n  this.speciality;\n  this.beds = {};\n\n  this.get_bed = function (number) {\n    return this.beds[number];\n  };\n\n  this.add_bed = function (bed) {\n    // eslint-disable-next-line no-return-assign\n    return (this.beds[bed.number] = bed);\n  };\n};\n\nvar Bed = function (ward, number) {\n  this.ward = ward;\n  this.number = number;\n  this.gender;\n  this.patient;\n\n  this.admit = function (patient) {\n    this.patient = patient;\n    // eslint-disable-next-line no-return-assign\n    this.patient.template = this.patient.speciality === this.ward.speciality ? 'on' : 'off';\n  };\n};\n\nmodule.exports = {\n  Patient: Patient,\n  Hospital: Hospital,\n  Ward: Ward,\n  Bed: Bed,\n};\n"
  },
  {
    "path": "test/scores/MultiScoreTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar MultiScore = require('../../lib/scores/MultiScore');\n\ndescribe('MultiScore', function () {\n  it('should return true when first sub score wins', function () {\n    var m1 = new MultiScore([new SimpleScore(1)]);\n    var m2 = new MultiScore([new SimpleScore(0)]);\n\n    assert.ok(m1.compare(m2) > 0);\n  });\n\n  it('should return false when first sub score loses', function () {\n    var m1 = new MultiScore([new SimpleScore(0)]);\n    var m2 = new MultiScore([new SimpleScore(1)]);\n\n    assert.ok(m1.compare(m2) < 0);\n  });\n\n  it('should ignore subsequent scores after a win', function () {\n    var m1 = new MultiScore([new SimpleScore(1), new SimpleScore(0)]);\n    var m2 = new MultiScore([new SimpleScore(0), new SimpleScore(1)]);\n\n    assert.ok(m1.compare(m2) > 0);\n  });\n\n  it('should ignore subsequent scores after a loss', function () {\n    var m1 = new MultiScore([new SimpleScore(0), new SimpleScore(1)]);\n    var m2 = new MultiScore([new SimpleScore(1), new SimpleScore(0)]);\n\n    assert.ok(m1.compare(m2) < 0);\n  });\n\n  it('should return true when first sub score draws but second wins', function () {\n    var m1 = new MultiScore([new SimpleScore(0), new SimpleScore(1)]);\n    var m2 = new MultiScore([new SimpleScore(0), new SimpleScore(0)]);\n\n    assert.ok(m1.compare(m2) > 0);\n  });\n\n  function SimpleScore(value) {\n    this.value = value;\n    this.compare = function (other) {\n      return this.value - other.value;\n    };\n  }\n});\n"
  },
  {
    "path": "test/shims/FileSystemTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar fs = require('../../lib/shims').fs;\nvar path = require('../../lib/shims').path;\n\ndescribe('FileSystem', function () {\n  it('should check path existence', function () {\n    assert(fs.existsSync('./test/shims/data/subdir1'));\n    assert(fs.existsSync('./test/shims/data/file3.json'));\n    assert(fs.existsSync('test/shims/data/subdir2'));\n    assert(fs.existsSync('test/shims/data/subdir2/file2.feature'));\n    assert(fs.existsSync(path.join(__dirname, 'data/subdir1/file1.json')));\n    assert(!fs.existsSync('./test/shims/data/non.existent'));\n  });\n\n  it('should distinguish files and directories', function () {\n    var dirStat = fs.statSync('./test/shims/data/subdir1');\n    assert(dirStat.isDirectory());\n    var fileStat = fs.statSync('./test/shims/data/subdir2/file2.feature');\n    assert(!fileStat.isDirectory());\n  });\n\n  it('should get directory content for a single level depth', function () {\n    var content = fs.readdirSync('./test/shims/data');\n    assert.deepEqual(content.sort(), ['subdir1', 'subdir2', 'file3.json'].sort());\n  });\n\n  it('should get file content as string', function () {\n    var content = fs.readFileSync('./test/shims/data/subdir1/file1.json', 'utf8');\n    var json = JSON.parse(content);\n    assert.deepEqual(json, { x: 1, y: 2 });\n  });\n});\n"
  },
  {
    "path": "test/shims/PathTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar path = require('../../lib/shims').path;\nvar proc = require('../../lib/shims').process;\n\ndescribe('Path', function () {\n  it('should create absolute path from relative path', function () {\n    assert.strictEqual(path.resolve('x/y/z'), path.join(proc.cwd(), 'x/y/z'));\n  });\n\n  it('should normalize paths', function () {\n    assert.strictEqual(path.normalize('./x//y/./z').split('\\\\').join('/'), 'x/y/z');\n  });\n\n  it('should join paths', function () {\n    assert.strictEqual(path.join('x', 'y', 'z').split('\\\\').join('/'), 'x/y/z');\n  });\n});\n"
  },
  {
    "path": "test/shims/ProcessTests.js",
    "content": "'use strict';\n\nvar assert = require('assert');\nvar proc = require('../../lib/shims').process;\nvar path = require('../../lib/shims').path;\n\ndescribe('Process', function () {\n  it('should contain the working directory path', function () {\n    assert.strictEqual(proc.cwd(), path.resolve('.'));\n  });\n});\n"
  },
  {
    "path": "test/shims/data/file3.json",
    "content": "{\n  \"name\": \"file3\",\n  \"type\": \"json\"\n}\n"
  },
  {
    "path": "test/shims/data/subdir1/file1.json",
    "content": "{\n  \"x\": 1,\n  \"y\": 2\n}\n"
  },
  {
    "path": "test/shims/data/subdir2/file2.feature",
    "content": "Feature: blah\n  Scenario: bla-bla\n    When x\n    Then y"
  }
]